diff --git a/README.md b/README.md
index 5b7f091..8e56120 100644
--- a/README.md
+++ b/README.md
@@ -27,3 +27,6 @@ These branches are for bugfixes.
These branches are for javadoc and project documentation (such as the readme, class diagrams etc.).
+
+## User Manual
+- Search Plant List: if first Char is '#': only exact match in ID.
diff --git a/doc/Classdiagramm/layer-diagram.png b/doc/Classdiagramm/layer-diagram.png
new file mode 100644
index 0000000..6e6fdfe
Binary files /dev/null and b/doc/Classdiagramm/layer-diagram.png differ
diff --git a/doc/Classdiagramm/layer-diagram.uxf b/doc/Classdiagramm/layer-diagram.uxf
new file mode 100644
index 0000000..6330af5
--- /dev/null
+++ b/doc/Classdiagramm/layer-diagram.uxf
@@ -0,0 +1,7 @@
+10UMLPackage39060340100UIUMLPackage390180460120DomainUMLPackage390330460120Technical ServicesUMLPackage4009010060Views (JFX)UMLPackage40022010060IOUMLPackage40037010060JacksonUMLPackage51022010060TypesUMLPackage62022010060ModelsUMLPackage5109011060Controllers (JFX)UMLPackage51037010060LoggingUMLPackage62037010060JavaFXUMLPackage73022011060ServicesUMLPackage73037011060HTTP/APIRelation5701509070lt=.>
+70;10;10;50Relation57029011080lt=.>
+90;10;10;60Relation340120350400lt=.>
+60;10;10;10;10;380;330;380;330;310Relation77027030120lt=.>
+10;10;10;100Relation36025060180lt=.>
+40;10;10;10;10;160;40;160Relation61012070120lt=.>
+10;10;50;10;50;100
\ No newline at end of file
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java b/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java
index 0d70b44..fd31017 100644
--- a/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java
+++ b/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java
@@ -10,9 +10,9 @@ import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
- FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
- Scene scene = new Scene(fxmlLoader.load(), 320, 240);
- stage.setTitle("Hello!");
+ FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("MainFXML.fxml"));
+ Scene scene = new Scene(fxmlLoader.load());
+ stage.setTitle("Gartenverwaltung");
stage.setScene(scene);
stage.show();
}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/HomeController.java b/src/main/java/ch/zhaw/gartenverwaltung/HomeController.java
new file mode 100644
index 0000000..7df4661
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/HomeController.java
@@ -0,0 +1,5 @@
+package ch.zhaw.gartenverwaltung;
+
+public class HomeController
+{
+}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java b/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java
new file mode 100644
index 0000000..c3fe04d
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java
@@ -0,0 +1,94 @@
+package ch.zhaw.gartenverwaltung;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.Initializable;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.layout.AnchorPane;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Objects;
+import java.util.ResourceBundle;
+
+public class MainFXMLController implements Initializable {
+
+ @FXML
+ private Button home_button;
+
+ @FXML
+ private AnchorPane mainPane;
+
+ @FXML
+ private Button myPlants_button;
+
+ @FXML
+ private Button mySchedule_button;
+
+ @FXML
+ private Button plants_button;
+
+ @FXML
+ void goToHome(ActionEvent event) throws IOException {
+ loadPane("Home.fxml");
+ styleChangeButton(home_button);
+ }
+
+ @FXML
+ void goToMyPlants(ActionEvent event) throws IOException {
+ loadPane("MyPlants.fxml");
+ styleChangeButton(myPlants_button);
+ }
+
+ @FXML
+ void goToMySchedule(ActionEvent event) throws IOException {
+ loadPane("MySchedule.fxml");
+ styleChangeButton(mySchedule_button);
+ }
+
+ @FXML
+ void goToPlants(ActionEvent event) throws IOException {
+ loadPane("Plants.fxml");
+ styleChangeButton(plants_button);
+ }
+
+ /**
+ * Updates the mainPane with the selected fxml file.
+ * set HGrow and VGrow to parent AnchorPane.
+ * Sends MainController to other Controllers.
+ * @param fxmlFile string of fxml file
+ * @throws IOException exception when file does not exist
+ */
+ public void loadPane(String fxmlFile) throws IOException {
+ //ToDo HGrow and VGrow of new node
+ Node node;
+ FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(HelloApplication.class.getResource(fxmlFile)));
+ node = (Node)loader.load();
+ if(fxmlFile.equals("MyPlants.fxml")) {
+ MyPlantsController myPlantsController = loader.getController();
+ myPlantsController.getMainController(this);
+ }
+ mainPane.getChildren().setAll(node);
+ }
+
+ private void styleChangeButton(Button button) {
+ //ToDo changeStyle of the menu buttons
+ }
+
+ /**
+ * loads the default FXML File
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ try {
+ loadPane("Home.fxml");
+ styleChangeButton(home_button);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
+
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java
new file mode 100644
index 0000000..e223e8b
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java
@@ -0,0 +1,58 @@
+package ch.zhaw.gartenverwaltung;
+
+import ch.zhaw.gartenverwaltung.types.Plant;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.layout.VBox;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class MyPlantsController implements Initializable {
+ MainFXMLController mainController;
+
+ @FXML
+ private Button addPlant_button;
+
+ @FXML
+ private VBox myPlants_vbox;
+
+ @FXML
+ void addPlant(ActionEvent event) throws IOException {
+ mainController.loadPane("Plants.fxml");
+ }
+
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ //ToDo
+ List myPlants = getMyPlants();
+ createPlantView(myPlants);
+ }
+
+ private void createPlantView(List myPlants) {
+ //ToDo
+ for(Plant plant : myPlants) {
+ createPlantView();
+ }
+ }
+
+ public void getMainController(MainFXMLController controller) {
+ mainController = controller;
+ }
+
+ private List getMyPlants() {
+ //ToDo method to get myPlantList(scheduled)
+ //Method to call all Plants saved
+ List myPlantList = new LinkedList<>();
+ return myPlantList;
+ }
+
+ private void createPlantView() {
+ //ToDo FXML Panel with Plant data
+ }
+}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java
new file mode 100644
index 0000000..b16445a
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java
@@ -0,0 +1,124 @@
+package ch.zhaw.gartenverwaltung;
+
+import ch.zhaw.gartenverwaltung.types.Plant;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListCell;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.Pane;
+
+import java.net.URL;
+import java.time.LocalDate;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class MyScheduleController implements Initializable {
+ private Plant selectedPlant = null;
+
+ @FXML
+ private Label day1_label;
+
+ @FXML
+ private Pane day1_pane;
+
+ @FXML
+ private Label day2_label;
+
+ @FXML
+ private Pane day2_pane;
+
+ @FXML
+ private Label day3_label;
+
+ @FXML
+ private Pane day3_pane;
+
+ @FXML
+ private Label day4_label;
+
+ @FXML
+ private Pane day4_pane;
+
+ @FXML
+ private Label day5_label;
+
+ @FXML
+ private Pane day5_pane;
+
+ @FXML
+ private Label day6_label;
+
+ @FXML
+ private Pane day6_pane;
+
+ @FXML
+ private Label day7_label;
+
+ @FXML
+ private Pane day7_pane;
+
+ @FXML
+ private Label information_label;
+
+ @FXML
+ private ListView scheduledPlants_listview;
+
+ @Override
+ public void initialize(URL location, ResourceBundle resources) {
+ List plantList = new LinkedList<>();
+ fillListViewMyPlantsInSchedule(plantList);
+ getSelectedPlantTask();
+ setDayLabels();
+ information_label.setText("");
+ }
+
+ private void getSelectedPlantTask() {
+ scheduledPlants_listview.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
+ @Override
+ public void changed(ObservableValue extends Plant> observable, Plant oldValue, Plant newValue) {
+ if(newValue != null) {
+ selectedPlant = newValue;
+ //ToDo update day_panel with task for the day
+ } else {
+ selectedPlant = null;
+ //ToDo update day_panel with task for the day (all plants)
+ }
+ }
+ });
+ }
+
+ private void setDayLabels() {
+ LocalDate today = LocalDate.now();
+ day1_label.setText(today.getDayOfWeek().toString());
+ day2_label.setText(today.plusDays(1).getDayOfWeek().toString());
+ day3_label.setText(today.plusDays(2).getDayOfWeek().toString());
+ day4_label.setText(today.plusDays(3).getDayOfWeek().toString());
+ day5_label.setText(today.plusDays(4).getDayOfWeek().toString());
+ day6_label.setText(today.plusDays(5).getDayOfWeek().toString());
+ day7_label.setText(today.plusDays(6).getDayOfWeek().toString());
+ }
+
+ private void fillListViewMyPlantsInSchedule(List list) {
+ for (Plant plant : list) {
+ scheduledPlants_listview.getItems().add(plant);
+ }
+ scheduledPlants_listview.setCellFactory(param -> new ListCell() {
+ @Override
+ protected void updateItem(Plant plant, boolean empty) {
+ super.updateItem(plant, empty);
+
+ if (empty || plant == null || plant.name() == null) {
+ setText(null);
+ } else {
+ setText(plant.name());
+ }
+ }
+ });
+ }
+
+
+}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java b/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java
new file mode 100644
index 0000000..a8c8d93
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java
@@ -0,0 +1,186 @@
+package ch.zhaw.gartenverwaltung;
+
+import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
+import ch.zhaw.gartenverwaltung.plantList.PlantListModel;
+import ch.zhaw.gartenverwaltung.types.HardinessZone;
+import ch.zhaw.gartenverwaltung.types.Plant;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.*;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.InputMethodEvent;
+import javafx.scene.layout.VBox;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class PlantsController implements Initializable {
+ private final PlantListModel plantListModel = new PlantListModel();
+ private Plant selectedPlant = null;
+ private final HardinessZone DEFAULT_HARDINESS_ZONE = HardinessZone.ZONE_8A;
+
+ @FXML
+ private CheckBox autum_filter;
+
+ @FXML
+ private VBox climate_zones;
+
+ @FXML
+ private Label description_plant;
+
+ @FXML
+ private ImageView img_plant;
+
+ @FXML
+ private ListView list_plants;
+
+ @FXML
+ private Button saveToMyPlant_button;
+
+ @FXML
+ private TextField search_plants;
+
+ @FXML
+ private CheckBox sommer_filter;
+
+ @FXML
+ private CheckBox spring_filter;
+
+ @FXML
+ private CheckBox winter_filter;
+
+ @FXML
+ void filterAutum(ActionEvent event) {
+ //ToDo
+
+ }
+
+ @FXML
+ void filterSommer(ActionEvent event) {
+ //ToDo
+
+ }
+
+ @FXML
+ void filterSpring(ActionEvent event) {
+ //ToDo
+
+ }
+
+ @FXML
+ void filterWinter(ActionEvent event) {
+ //ToDo
+
+ }
+
+ @FXML
+ void saveToMyPlant(ActionEvent event) {
+ //ToDo model save selectedPlant to mySelectedPlant(IO)
+ }
+
+ @FXML
+ void searchForPlant(InputMethodEvent event) {
+ viewFilteredListBySearch(search_plants.getText());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(URL url, ResourceBundle resourceBundle) {
+ List plantList = new LinkedList<>();
+ try {
+ plantList = plantListModel.getPlantList(DEFAULT_HARDINESS_ZONE);
+ } catch (HardinessZoneNotSetException | IOException e) {
+ e.printStackTrace();
+ }
+ fillListViewWithData(plantList);
+
+ description_plant.setText("");
+ saveToMyPlant_button.setDisable(true);
+
+ createFilterHardinessZone();
+ lookForSelectedListEntry();
+ }
+
+ /**
+ * update the ListView according to the plant list provided
+ * Entry in ListView is plant name
+ * @param list plantList which fill the ListView
+ */
+ private void fillListViewWithData(List list) {
+ clearListView();
+ for (Plant plant : list) {
+ list_plants.getItems().add(plant);
+ }
+ list_plants.setCellFactory(param -> new ListCell() {
+ @Override
+ protected void updateItem(Plant plant, boolean empty) {
+ super.updateItem(plant, empty);
+
+ if (empty || plant == null || plant.name() == null) {
+ setText(null);
+ } else {
+ setText(plant.name());
+ }
+ }
+ });
+ }
+
+ private void viewFilteredListByFilters() {
+ boolean springValue = spring_filter.isSelected();
+ boolean sommerValue = sommer_filter.isSelected();
+ boolean autumValue = autum_filter.isSelected();
+ boolean winterValue = winter_filter.isSelected();
+ //ToDo getFilteredPlantList with (plantListModel.getFilteredPlantList(DEFAULT_HARDINESS_ZONE, ))
+ //List plantList = new LinkedList<>();
+ //fillListViewWithData(plantList);
+ }
+
+ private void viewFilteredListBySearch(String query) {
+ //ToDo getFilteredPlantList with (plantListModel.getFilteredPlantList(DEFAULT_HARDINESS_ZONE, ))
+ //List plantList = new LinkedList<>();
+ //fillListViewWithData(plantList);
+ }
+
+ private void createFilterHardinessZone() {
+ //ToDo create radioList of hardinessZone in VBox climate_zones
+ }
+
+ /**
+ * observes changes in the selectedProperty of ListView and updates the description label
+ */
+ private void lookForSelectedListEntry() {
+ list_plants.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
+ @Override
+ public void changed(ObservableValue extends Plant> observable, Plant oldValue, Plant newValue) {
+ //ToDo
+ if(newValue != null) {
+ selectedPlant = newValue;
+ description_plant.setText(selectedPlant.description());
+ saveToMyPlant_button.setDisable(false);
+ //update img plant
+ } else {
+ selectedPlant = null;
+ description_plant.setText("");
+ saveToMyPlant_button.setDisable(true);
+ //update img when null placeholder PNG
+ }
+ }
+ });
+ }
+
+
+ /**
+ * clears the ListView of entries
+ */
+ private void clearListView() {
+ list_plants.getItems().clear();
+ }
+}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabase.java b/src/main/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabase.java
index aa06e65..b7c982a 100644
--- a/src/main/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabase.java
+++ b/src/main/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabase.java
@@ -1,10 +1,13 @@
package ch.zhaw.gartenverwaltung.io;
+import ch.zhaw.gartenverwaltung.json.PlantImageDeserializer;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.MonthDayDeserializer;
+import javafx.scene.image.Image;
import java.io.IOException;
import java.net.URL;
@@ -31,10 +34,14 @@ public class JsonPlantDatabase implements PlantDatabase {
* Creating constant objects required to deserialize the {@link MonthDay} classes
*/
private final static JavaTimeModule timeModule = new JavaTimeModule();
+ private final static SimpleModule imageModule = new SimpleModule();
+
static {
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("MM-dd");
MonthDayDeserializer dateDeserializer = new MonthDayDeserializer(dateFormat);
timeModule.addDeserializer(MonthDay.class, dateDeserializer);
+
+ imageModule.addDeserializer(Image.class, new PlantImageDeserializer());
}
/**
@@ -75,8 +82,9 @@ public class JsonPlantDatabase implements PlantDatabase {
}
if (dataSource != null) {
currentZone = zone;
- ObjectMapper mapper = new ObjectMapper();
- mapper.registerModule(timeModule);
+ ObjectMapper mapper = new ObjectMapper()
+ .registerModule(timeModule)
+ .registerModule(imageModule);
List result;
result = mapper.readerForListOf(Plant.class).readValue(dataSource);
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/json/GrowthPhaseTypeDeserializer.java b/src/main/java/ch/zhaw/gartenverwaltung/json/GrowthPhaseTypeDeserializer.java
index f3bb60f..285536a 100644
--- a/src/main/java/ch/zhaw/gartenverwaltung/json/GrowthPhaseTypeDeserializer.java
+++ b/src/main/java/ch/zhaw/gartenverwaltung/json/GrowthPhaseTypeDeserializer.java
@@ -17,11 +17,12 @@ public class GrowthPhaseTypeDeserializer extends StdDeserializer {
@Override
public HardinessZone deserialize(JsonParser parser, DeserializationContext context) throws IOException {
HardinessZone result = null;
+ String token = parser.getText();
try {
- result = HardinessZone.valueOf(parser.getText().toUpperCase());
+ result = HardinessZone.valueOf(token.toUpperCase());
} catch (IllegalArgumentException e) {
// TODO: Log
- System.err.println("bad growth phase type");
+ System.err.printf("Unknown Hardiness Zone \"%s\"\n", token);
}
return result;
}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/json/PlantImageDeserializer.java b/src/main/java/ch/zhaw/gartenverwaltung/json/PlantImageDeserializer.java
new file mode 100644
index 0000000..e5611fc
--- /dev/null
+++ b/src/main/java/ch/zhaw/gartenverwaltung/json/PlantImageDeserializer.java
@@ -0,0 +1,31 @@
+package ch.zhaw.gartenverwaltung.json;
+
+import ch.zhaw.gartenverwaltung.io.PlantDatabase;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import javafx.scene.image.Image;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+public class PlantImageDeserializer extends JsonDeserializer {
+
+ @Override
+ public Image deserialize(JsonParser parser, DeserializationContext context) throws IOException {
+ Image result = null;
+ URL imageUrl = PlantDatabase.class.getResource(String.format("images/%s", parser.getText()));
+ if (imageUrl != null) {
+ try (InputStream is = new FileInputStream(imageUrl.getFile())) {
+ result = new Image(is);
+ } catch (IllegalArgumentException e) {
+ // TODO: Log
+ e.printStackTrace();
+ System.err.printf("Cannot find Image \"%s\"\n", imageUrl.getFile());
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/plantList/PlantListModel.java b/src/main/java/ch/zhaw/gartenverwaltung/plantList/PlantListModel.java
index bd12a28..8e8a1b8 100644
--- a/src/main/java/ch/zhaw/gartenverwaltung/plantList/PlantListModel.java
+++ b/src/main/java/ch/zhaw/gartenverwaltung/plantList/PlantListModel.java
@@ -3,14 +3,17 @@ package ch.zhaw.gartenverwaltung.plantList;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.io.JsonPlantDatabase;
import ch.zhaw.gartenverwaltung.io.PlantDatabase;
+import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import java.io.IOException;
+import java.time.MonthDay;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
public class PlantListModel {
private PlantDatabase plantDatabase;
@@ -19,8 +22,8 @@ public class PlantListModel {
/**
* Comparators to create sorted Plant List
*/
- static final Comparator sortByName = (Plant o1, Plant o2) -> o1.name().compareTo(o2.name());
- static final Comparator SortById = (Plant o1, Plant o2) -> Long.compare(o1.id(), o2.id());
+ static final Comparator sortByName = Comparator.comparing(Plant::name);
+ static final Comparator SortById = Comparator.comparingLong(Plant::id);
/**
* Constructor to create Database Object.
@@ -67,7 +70,7 @@ public class PlantListModel {
*/
public List getSortedPlantList(HardinessZone zone, Comparator comparator) throws HardinessZoneNotSetException, IOException {
setCurrentZone(zone);
- return plantDatabase.getPlantList(zone).stream().sorted(comparator).toList();
+ return plantDatabase.getPlantList(zone).stream().sorted(comparator).collect(Collectors.toList());
}
/**
@@ -80,7 +83,7 @@ public class PlantListModel {
*/
public List getFilteredPlantList(HardinessZone zone, Predicate predicate) throws HardinessZoneNotSetException, IOException {
setCurrentZone(zone);
- return getPlantList(zone).stream().filter(predicate).toList();
+ return getPlantList(zone).stream().filter(predicate).collect(Collectors.toList());
}
/**
@@ -97,4 +100,66 @@ public class PlantListModel {
plantDatabase.getPlantById(zone, id).ifPresent(plantList::add);
return plantList;
}
+
+ /**
+ *
+ * @param zone selected hardiness zone
+ * @param searchString the string to search plant List, set '#' as first char the search by id.
+ * @return List of plants found in Plant List which contain the search String in the name or description
+ * @throws HardinessZoneNotSetException If no {@link HardinessZone} was specified
+ * @throws IOException If the database cannot be accessed
+ */
+ public List getFilteredPlantListByString(HardinessZone zone, String searchString) throws HardinessZoneNotSetException, IOException {
+ if(searchString.length() == 0){
+ return getPlantList(zone);
+ } else if(searchString.charAt(0) == '#') {
+ try {
+ return getFilteredPlantListById(zone, Long.parseLong(searchString.substring(1)));
+ } catch (NumberFormatException e) {
+ return new ArrayList<>();
+ }
+ } else {
+ return getFilteredPlantList(zone, plant -> plant.name().contains(searchString) || plant.description().contains(searchString));
+ }
+ }
+
+ /**
+ *
+ * @param type GrowPhaseType to filter
+ * @param zone selected hardiness zone
+ * @param from the earliest date to for the filter
+ * @param to the lastest date for the filter
+ * @return List of Plants with selected saison
+ * @throws HardinessZoneNotSetException If no {@link HardinessZone} was specified
+ * @throws IOException If the database cannot be accessed
+ */
+ private List getFilteredPlantListBySaison(GrowthPhaseType type, HardinessZone zone, MonthDay from, MonthDay to) throws HardinessZoneNotSetException, IOException {
+ return getFilteredPlantList(zone, plant -> plant.lifecycle().stream().anyMatch(growthPhase -> growthPhase.startDate().compareTo(from) >= 0 && (growthPhase.startDate().compareTo(to) <= 0) && growthPhase.type() == type));
+ }
+
+ /**
+ *
+ * @param zone selected hardiness zone
+ * @param from the earliest date to for the filter
+ * @param to the lastest date for the filter
+ * @return List of Plants with selected saison
+ * @throws HardinessZoneNotSetException If no {@link HardinessZone} was specified
+ * @throws IOException If the database cannot be accessed
+ */
+ public List getFilteredPlantListByPlantingSaison(HardinessZone zone, MonthDay from, MonthDay to) throws HardinessZoneNotSetException, IOException {
+ return getFilteredPlantListBySaison(GrowthPhaseType.PLANT, zone, from, to);
+ }
+
+ /**
+ *
+ * @param zone selected hardiness zone
+ * @param from the earliest date to for the filter
+ * @param to the lastest date for the filter
+ * @return List of Plants with selected saison
+ * @throws HardinessZoneNotSetException If no {@link HardinessZone} was specified
+ * @throws IOException If the database cannot be accessed
+ */
+ public List getFilteredPlantListByHarvestSaison(HardinessZone zone, MonthDay from, MonthDay to) throws HardinessZoneNotSetException, IOException {
+ return getFilteredPlantListBySaison(GrowthPhaseType.HARVEST, zone, from, to);
+ }
}
diff --git a/src/main/java/ch/zhaw/gartenverwaltung/types/Plant.java b/src/main/java/ch/zhaw/gartenverwaltung/types/Plant.java
index 13652a6..3250b4f 100644
--- a/src/main/java/ch/zhaw/gartenverwaltung/types/Plant.java
+++ b/src/main/java/ch/zhaw/gartenverwaltung/types/Plant.java
@@ -1,7 +1,10 @@
package ch.zhaw.gartenverwaltung.types;
+import javafx.scene.image.Image;
+
import java.time.LocalDate;
import java.util.List;
+import java.util.stream.Collectors;
import static java.time.temporal.ChronoUnit.DAYS;
@@ -9,6 +12,7 @@ public record Plant(
long id,
String name,
String description,
+ Image image,
String spacing,
int light,
String soil,
@@ -22,7 +26,7 @@ public record Plant(
public List lifecycleForGroup(int group) {
return lifecycle.stream()
.filter(growthPhase -> growthPhase.group() != group)
- .toList();
+ .collect(Collectors.toList());
}
public LocalDate sowDateFromHarvestDate(LocalDate harvestDate, int group) {
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/Home.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/Home.fxml
new file mode 100644
index 0000000..2bd24b3
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/Home.fxml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml
new file mode 100644
index 0000000..569a89d
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/MyPlants.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/MyPlants.fxml
new file mode 100644
index 0000000..56a0edb
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/MyPlants.fxml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/MySchedule.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/MySchedule.fxml
new file mode 100644
index 0000000..b778d50
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/MySchedule.fxml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/Plants.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/Plants.fxml
new file mode 100644
index 0000000..0cb3c6d
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/Plants.fxml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/images/ATTRIBUTION b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/ATTRIBUTION
new file mode 100644
index 0000000..4fdeb79
--- /dev/null
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/ATTRIBUTION
@@ -0,0 +1,5 @@
+Potato, Onion
+ Photos by Lars Blankers: https://unsplash.com/@lmablankers?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
+
+Carrot
+ Photo by Maja Vujic: https://unsplash.com/@majavujic87?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
\ No newline at end of file
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/images/carrot.jpg b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/carrot.jpg
new file mode 100644
index 0000000..41b3343
Binary files /dev/null and b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/carrot.jpg differ
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/images/onion.jpg b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/onion.jpg
new file mode 100644
index 0000000..20c95e8
Binary files /dev/null and b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/onion.jpg differ
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/images/potato.jpg b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/potato.jpg
new file mode 100644
index 0000000..b62660e
Binary files /dev/null and b/src/main/resources/ch/zhaw/gartenverwaltung/io/images/potato.jpg differ
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/io/plantdb.json b/src/main/resources/ch/zhaw/gartenverwaltung/io/plantdb.json
index 927835d..5a23d09 100644
--- a/src/main/resources/ch/zhaw/gartenverwaltung/io/plantdb.json
+++ b/src/main/resources/ch/zhaw/gartenverwaltung/io/plantdb.json
@@ -6,6 +6,7 @@
"light": 6,
"spacing": "35",
"soil": "sandy",
+ "image": "potato.jpg",
"pests": [
{
"name": "Rot",
@@ -86,6 +87,7 @@
"id": 1,
"name": "Early Carrot",
"description": "Carrot, (Daucus carota), herbaceous, generally biennial plant of the Apiaceae family that produces an edible taproot. Among common varieties root shapes range from globular to long, with lower ends blunt to pointed. Besides the orange-coloured roots, white-, yellow-, and purple-fleshed varieties are known.",
+ "image": "carrot.jpg",
"lifecycle": [
{
"startDate": "02-20",
@@ -167,6 +169,7 @@
"id": 2,
"name": "Summertime Onion",
"description": "Onion, (Allium cepa), herbaceous biennial plant in the amaryllis family (Amaryllidaceae) grown for its edible bulb. The onion is likely native to southwestern Asia but is now grown throughout the world, chiefly in the temperate zones. Onions are low in nutrients but are valued for their flavour and are used widely in cooking. They add flavour to such dishes as stews, roasts, soups, and salads and are also served as a cooked vegetable.",
+ "image": "onion.jpg",
"lifecycle": [
{
"startDate": "03-15",
diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/placeholder.png b/src/main/resources/ch/zhaw/gartenverwaltung/placeholder.png
new file mode 100644
index 0000000..dae1647
Binary files /dev/null and b/src/main/resources/ch/zhaw/gartenverwaltung/placeholder.png differ
diff --git a/src/test/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabaseTest.java b/src/test/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabaseTest.java
index b554502..a21b440 100644
--- a/src/test/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabaseTest.java
+++ b/src/test/java/ch/zhaw/gartenverwaltung/io/JsonPlantDatabaseTest.java
@@ -30,9 +30,7 @@ public class JsonPlantDatabaseTest {
List testList;
try {
testList = testDatabase.getPlantList(HardinessZone.ZONE_8A);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (HardinessZoneNotSetException e) {
+ } catch (IOException | HardinessZoneNotSetException e) {
throw new RuntimeException(e);
}
Assertions.assertEquals(3, testList.size());
@@ -47,11 +45,8 @@ public class JsonPlantDatabaseTest {
void getPlantById() {
Optional testPlant;
try {
- testDatabase.getPlantList(HardinessZone.ZONE_8A);
- testPlant = testDatabase.getPlantById(1);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (HardinessZoneNotSetException e) {
+ testPlant = testDatabase.getPlantById(HardinessZone.ZONE_8A,1);
+ } catch (IOException | HardinessZoneNotSetException e) {
throw new RuntimeException(e);
}
Assertions.assertTrue(testPlant.isPresent());
@@ -63,11 +58,8 @@ public class JsonPlantDatabaseTest {
void getPlantByIdMustFail() {
Optional testPlant;
try {
- testDatabase.getPlantList(HardinessZone.ZONE_8A);
- testPlant = testDatabase.getPlantById(99);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } catch (HardinessZoneNotSetException e) {
+ testPlant = testDatabase.getPlantById(HardinessZone.ZONE_8A,99);
+ } catch (IOException | HardinessZoneNotSetException e) {
throw new RuntimeException(e);
}
Assertions.assertFalse(testPlant.isPresent());
diff --git a/src/test/java/ch/zhaw/gartenverwaltung/plantList/PlantListModelTest.java b/src/test/java/ch/zhaw/gartenverwaltung/plantList/PlantListModelTest.java
index 0aecc35..9ed857d 100644
--- a/src/test/java/ch/zhaw/gartenverwaltung/plantList/PlantListModelTest.java
+++ b/src/test/java/ch/zhaw/gartenverwaltung/plantList/PlantListModelTest.java
@@ -3,14 +3,14 @@ package ch.zhaw.gartenverwaltung.plantList;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.io.JsonPlantDatabase;
import ch.zhaw.gartenverwaltung.io.PlantDatabase;
-import ch.zhaw.gartenverwaltung.types.HardinessZone;
-import ch.zhaw.gartenverwaltung.types.Plant;
+import ch.zhaw.gartenverwaltung.types.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
+import java.time.MonthDay;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
@@ -43,31 +43,39 @@ class PlantListModelTest {
20,
"summertime onion",
"Onion, (Allium cepa), herbaceous biennial plant in the amaryllis family (Amaryllidaceae) grown for its edible bulb. The onion is likely native to southwestern Asia but is now grown throughout the world, chiefly in the temperate zones. Onions are low in nutrients but are valued for their flavour and are used widely in cooking. They add flavour to such dishes as stews, roasts, soups, and salads and are also served as a cooked vegetable.",
+ null,
"15,30,2",
0,
"sandy to loamy, loose soil, free of stones",
new ArrayList<>(),
- new ArrayList<>())
+ List.of(new GrowthPhase(MonthDay.of(6, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.HARVEST, HardinessZone.ZONE_8A, new ArrayList<>()),
+ new GrowthPhase(MonthDay.of(4, 3), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
+ new GrowthPhase(MonthDay.of(8, 5), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
+ new GrowthPhase(MonthDay.of(2, 8), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
+ new GrowthPhase(MonthDay.of(10, 2), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())))
);
examplePlantList.add(new Plant(
0,
"Potato",
"The potato is a tuber, round or oval, with small white roots called 'eyes', that are growth buds. The size varies depending on the variety; the colour of the skin can be white, yellow or even purple.",
+ null,
"35",
6,
"sandy",
new ArrayList<>(),
- new ArrayList<>())
+ List.of(new GrowthPhase(MonthDay.of(6, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.HARVEST, HardinessZone.ZONE_8A, new ArrayList<>()),
+ new GrowthPhase(MonthDay.of(6, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())))
);
examplePlantList.add(new Plant(
1,
"Early Carrot",
"Carrot, (Daucus carota), herbaceous, generally biennial plant of the Apiaceae family that produces an edible taproot. Among common varieties root shapes range from globular to long, with lower ends blunt to pointed. Besides the orange-coloured roots, white-, yellow-, and purple-fleshed varieties are known.",
+ null,
"5,35,2.5",
0,
"sandy to loamy, loose soil, free of stones",
new ArrayList<>(),
- new ArrayList<>())
+ List.of(new GrowthPhase(MonthDay.of(4, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())))
);
}
@@ -146,4 +154,46 @@ class PlantListModelTest {
assertEquals(1, plantListResult.size());
assertEquals(examplePlantList.get(0), plantListResult.get(0));
}
+
+ @Test
+ void getFilteredPlantListByString() throws HardinessZoneNotSetException, IOException {
+ model.setCurrentZone(HardinessZone.ZONE_1A);
+ List plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "#2");
+ assertEquals(0, plantListResult.size());
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "#20");
+ assertEquals(1, plantListResult.size());
+ assertEquals(examplePlantList.get(0), plantListResult.get(0));
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "#a2");
+ assertEquals(0, plantListResult.size());
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "onion");
+ assertEquals(1, plantListResult.size());
+ assertEquals(examplePlantList.get(0), plantListResult.get(0));
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "white roots");
+ assertEquals(1, plantListResult.size());
+ assertEquals(examplePlantList.get(1), plantListResult.get(0));
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "apple");
+ assertEquals(0, plantListResult.size());
+ plantListResult = model.getFilteredPlantListByString(HardinessZone.ZONE_8A, "");
+ assertEquals(3, plantListResult.size());
+ }
+
+ @Test
+ void getFilteredPlantListByPlantingSaison() throws HardinessZoneNotSetException, IOException {
+ model.setCurrentZone(HardinessZone.ZONE_1A);
+ List plantListResult = model.getFilteredPlantListByPlantingSaison(HardinessZone.ZONE_8A, MonthDay.of(4, 4), MonthDay.of(8, 4));
+ assertEquals(2, plantListResult.size());
+ assertEquals(examplePlantList.get(2), plantListResult.get(0));
+ assertEquals(examplePlantList.get(1), plantListResult.get(1));
+ }
+
+ @Test
+ void getFilteredPlantListByHarvestSaison() throws HardinessZoneNotSetException, IOException {
+ model.setCurrentZone(HardinessZone.ZONE_1A);
+ List plantListResult = model.getFilteredPlantListByHarvestSaison(HardinessZone.ZONE_8A, MonthDay.of(4, 4), MonthDay.of(8, 4));
+ assertEquals(2, plantListResult.size());
+ assertEquals(examplePlantList.get(1), plantListResult.get(0));
+ assertEquals(examplePlantList.get(0), plantListResult.get(1));
+ }
+
+
}