View Javadoc
1   /*
2    * Copyright (c) Patrick Magauran 2018.
3    *   Licensed under the AGPLv3. All conditions of said license apply.
4    *       This file is part of ABOS.
5    *
6    *       ABOS is free software: you can redistribute it and/or modify
7    *       it under the terms of the GNU Affero General Public License as published by
8    *       the Free Software Foundation, either version 3 of the License, or
9    *       (at your option) any later version.
10   *
11   *       ABOS is distributed in the hope that it will be useful,
12   *       but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *       GNU Affero General Public License for more details.
15   *
16   *       You should have received a copy of the GNU Affero General Public License
17   *       along with ABOS.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package Controllers;
21  
22  import Utilities.*;
23  import javafx.application.Platform;
24  import javafx.collections.FXCollections;
25  import javafx.collections.ObservableList;
26  import javafx.event.ActionEvent;
27  import javafx.fxml.FXML;
28  import javafx.geometry.Insets;
29  import javafx.scene.control.*;
30  import javafx.scene.control.cell.ComboBoxTableCell;
31  import javafx.scene.control.cell.PropertyValueFactory;
32  import javafx.scene.control.cell.TextFieldTableCell;
33  import javafx.scene.layout.GridPane;
34  import javafx.stage.FileChooser;
35  import javafx.stage.Stage;
36  import javafx.stage.Window;
37  import javafx.util.Pair;
38  import org.w3c.dom.*;
39  
40  import javax.xml.parsers.DocumentBuilder;
41  import javax.xml.parsers.DocumentBuilderFactory;
42  import javax.xml.parsers.ParserConfigurationException;
43  import javax.xml.transform.*;
44  import javax.xml.transform.dom.DOMSource;
45  import javax.xml.transform.stream.StreamResult;
46  import java.io.*;
47  import java.math.BigDecimal;
48  import java.time.LocalDate;
49  import java.util.*;
50  
51  //import javax.swing.*;
52  //import javax.swing.border.EmptyBorder;
53  //import javax.swing.table.DefaultTableModel;
54  //import java.awt.*;
55  //import java.awt.*;
56  @SuppressWarnings("WeakerAccess")
57  
58  public class AddYearController {
59  
60      @FXML
61      private TextField yearText;
62      @FXML
63      private TableView<formattedProductProps> ProductTable;
64      @FXML
65      private TextField itemTb;
66      @FXML
67      private TextField sizeTb;
68      @FXML
69      private TextField rateTb;
70      @FXML
71      private TextField idTb;
72      //private final JDialog parent;
73      private Collection<Year.category> rowsCats = new ArrayList<Year.category>();
74      @FXML
75      private CheckBox chkboxCreateDatabase;
76      private ObservableList<String> categoriesTb = FXCollections.observableArrayList();
77      @FXML
78      private ComboBox<String> categoriesCmbx;
79      //private DefaultTableModel tableModel;
80      private boolean newYear = false;
81      private ObservableList<formattedProductProps> data = FXCollections.observableArrayList();
82      private Window parentWindow;
83  
84      public AddYearController() {}
85  
86      /**
87       * Create the dialog.
88       */
89  
90      @FXML
91      private void tableFrmXML(ActionEvent event) {
92          FileChooser chooser = new FileChooser();
93          FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("XML files", "*.xml", "*.XML");
94          chooser.getExtensionFilters().add(filter);
95  
96          chooser.setSelectedExtensionFilter(filter);
97  //        logoLoc.setText(chooser.showOpenDialog(settings).getAbsolutePath());
98          File xmlFile = chooser.showOpenDialog(parentWindow);
99          if (xmlFile != null) {
100             String path = xmlFile.getAbsolutePath();
101             createTable(path);
102         }
103     }
104 
105     private void convert(String csvLoc, String xmlLoc) {
106         List<String> headers = new ArrayList<>(5);
107 
108 
109         File file = new File(csvLoc);
110 
111         try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
112 
113             DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
114             DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
115 
116             Document newDoc = domBuilder.newDocument();
117             // Root element
118             Element rootElement = newDoc.createElement("LawnGarden");
119             newDoc.appendChild(rootElement);
120 
121             int line = 0;
122 
123             String text;
124             while ((text = reader.readLine()) != null) {
125 
126                 StringTokenizer st = new StringTokenizer(text, ";", false);
127                 String[] rowValues = new String[st.countTokens()];
128                 int index = 0;
129                 while (st.hasMoreTokens()) {
130 
131                     String next = st.nextToken();
132                     rowValues[index] = next;
133                     index++;
134 
135                 }
136 
137                 //String[] rowValues = text.split(",");
138 
139                 if (line == 0) { // Header row
140                     Collections.addAll(headers, rowValues);
141                 } else { // Data row
142                     Element rowElement = newDoc.createElement("Products");
143                     rootElement.appendChild(rowElement);
144                     Attr attr = newDoc.createAttribute("id");
145                     attr.setValue(Integer.toString(line - 1));
146                     rowElement.setAttributeNode(attr);
147                     for (int col = 0; col < headers.size(); col++) {
148                         String header = headers.get(col);
149                         String value;
150 
151                         if (col < rowValues.length) {
152                             value = rowValues[col].trim();
153                         } else {
154                             // ?? Default value
155                             value = "";
156                         }
157 
158                         Element curElement = newDoc.createElement(header);
159                         curElement.appendChild(newDoc.createTextNode(value));
160                         rowElement.appendChild(curElement);
161                     }
162                 }
163                 line++;
164             }
165 
166             OutputStreamWriter osw = null;
167 
168             try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
169                 osw = new OutputStreamWriter(baos);
170 
171                 TransformerFactory tranFactory = TransformerFactory.newInstance();
172                 Transformer aTransformer = tranFactory.newTransformer();
173                 aTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
174                 aTransformer.setOutputProperty(OutputKeys.METHOD, "xml");
175                 //aTransformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
176                 aTransformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
177 
178                 Source src = new DOMSource(newDoc);
179                 Result result = new StreamResult(osw);
180                 aTransformer.transform(src, result);
181 
182                 osw.flush();
183                 //System.out.println(new String(baos.toByteArray()));
184 
185                 try (OutputStream outStream = new FileOutputStream(xmlLoc)) {// writing bytes in to byte output stream
186 
187                     baos.writeTo(outStream);
188                 } catch (IOException e) {
189                     LogToFile.log(e, Severity.SEVERE, "Error writing XML file. Please try again.");
190                 }
191 
192 
193             } catch (Exception exp) {
194                 LogToFile.log(exp, Severity.SEVERE, "Error writing XML file. Please try again.");
195             } finally {
196                 try {
197                     if (osw != null) {
198                         osw.close();
199                     }
200                 } catch (IOException e) {
201                     LogToFile.log(e, Severity.SEVERE, "Error closing file. Please try again.");
202                 }
203 
204             }
205         } catch (Exception e) {
206             LogToFile.log(e, Severity.SEVERE, "Error reading CSV file. Ensure the path exists, and the software has permission to read it.");
207         }
208     }
209 
210     @FXML
211     private void csvToXml(ActionEvent event) {
212         // Create the custom dialog.
213         Dialog<Pair<String, String>> dialog = new Dialog<>();
214         dialog.setTitle("CSV to XML conversion");
215 
216 // Set the button types.
217         ButtonType convertButtonType = new ButtonType("Convert", ButtonBar.ButtonData.OK_DONE);
218         dialog.getDialogPane().getButtonTypes().addAll(convertButtonType, ButtonType.CANCEL);
219 
220 // Create the username and password labels and fields.
221         GridPane grid = new GridPane();
222         grid.setHgap(10);
223         grid.setVgap(10);
224         grid.setPadding(new Insets(20, 150, 10, 10));
225 
226         TextField csvLoc = new TextField();
227         csvLoc.setPromptText("CSV file Location");
228         TextField xmlLoc = new TextField();
229         xmlLoc.setPromptText("XML Location");
230         Button getCsvLoc = new Button("...");
231         getCsvLoc.setOnAction(e -> {
232             FileChooser chooser = new FileChooser();
233             FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("CSV files", "*.csv", "*.CSV");
234             chooser.getExtensionFilters().add(filter);
235             chooser.setSelectedExtensionFilter(filter);
236             File csv = chooser.showOpenDialog(grid.getScene().getWindow());
237             if (csv != null) {
238                 String path = csv.getAbsolutePath();
239                 if (!path.toLowerCase().endsWith(".csv")) {
240                     path += ".csv";
241                 }
242                 csvLoc.setText(path);
243             }
244         });
245         Button getXmlLoc = new Button("...");
246         getXmlLoc.setOnAction(e -> {
247             FileChooser chooser = new FileChooser();
248             FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("XML files", "*.xml", "*.XML");
249             chooser.getExtensionFilters().add(filter);
250             chooser.setSelectedExtensionFilter(filter);
251             File XML = chooser.showSaveDialog(grid.getScene().getWindow());
252             if (XML != null) {
253                 String path = XML.getAbsolutePath();
254                 if (!path.toLowerCase().endsWith(".xml")) {
255                     path += ".xml";
256                 }
257                 xmlLoc.setText(path);
258             }
259         });
260         grid.add(new Label("CSV file Location:"), 0, 0);
261         grid.add(csvLoc, 1, 0);
262         grid.add(getCsvLoc, 2, 0);
263         grid.add(new Label("XML Location:"), 0, 1);
264         grid.add(xmlLoc, 1, 1);
265         grid.add(getXmlLoc, 2, 1);
266 
267 
268 // Enable/Disable login button depending on whether a username was entered.
269         javafx.scene.Node convertButton = dialog.getDialogPane().lookupButton(convertButtonType);
270         convertButton.setDisable(true);
271 
272 // Do some validation (using the Java 8 lambda syntax).
273         csvLoc.textProperty().addListener((observable, oldValue, newValue) -> convertButton.setDisable(newValue.trim().isEmpty()));
274 
275         dialog.getDialogPane().setContent(grid);
276 
277 // Request focus on the username field by default.
278         Platform.runLater(() -> csvLoc.requestFocus());
279 
280 // Convert the result to a username-password-pair when the login button is clicked.
281         dialog.setResultConverter(dialogButton -> {
282             if (dialogButton == convertButtonType) {
283                 return new Pair<>(csvLoc.getText(), xmlLoc.getText());
284             }
285             return null;
286         });
287 
288         Optional<Pair<String, String>> result = dialog.showAndWait();
289 
290         result.ifPresent(fileLocations -> {
291             convert(fileLocations.getKey(), fileLocations.getValue());
292             createTable(fileLocations.getValue());
293         });
294 
295 
296 
297 
298 /*        CSV2XML csv = new CSV2XML(parent);
299         String xmlFile = csv.getXML();
300         if (!xmlFile.isEmpty()) {
301             createTable(xmlFile);
302         }*/
303     }
304 
305     @FXML
306     private void catCmbxChanged(ActionEvent event) {
307         if (Objects.equals(categoriesCmbx.getSelectionModel().getSelectedItem(), "Add Category")) {
308             Dialog<Pair<String, String>> dialog = new Dialog<>();
309             dialog.setTitle("Add new category");
310 
311 // Set the button types.
312             ButtonType addCat = new ButtonType("Add", ButtonBar.ButtonData.OK_DONE);
313             dialog.getDialogPane().getButtonTypes().addAll(addCat, ButtonType.CANCEL);
314 
315 // Create the username and password labels and fields.
316             GridPane grid = new GridPane();
317             grid.setHgap(10);
318             grid.setVgap(10);
319             grid.setPadding(new Insets(20, 150, 10, 10));
320 
321             TextField catName = new TextField();
322             catName.setPromptText("Category Name");
323             DatePicker catDate = new DatePicker(LocalDate.now());
324             catDate.setPromptText("Category Due Date");
325 
326             grid.add(new Label("Category Name:"), 0, 0);
327             grid.add(catName, 1, 0);
328             grid.add(new Label("Category Due Date:"), 0, 1);
329             grid.add(catDate, 1, 1);
330 
331 
332 // Enable/Disable login button depending on whether a username was entered.
333             javafx.scene.Node addCatButton = dialog.getDialogPane().lookupButton(addCat);
334             addCatButton.setDisable(true);
335 
336 // Do some validation (using the Java 8 lambda syntax).
337             catName.textProperty().addListener((observable, oldValue, newValue) -> addCatButton.setDisable(newValue.trim().isEmpty()));
338 
339             dialog.getDialogPane().setContent(grid);
340 
341 // Request focus on the username field by default.
342             Platform.runLater(() -> catName.requestFocus());
343 
344 // Convert the result to a username-password-pair when the login button is clicked.
345             dialog.setResultConverter(dialogButton -> {
346                 if (dialogButton == addCat) {
347                     return new Pair<String, String>(catName.getText(), catDate.getValue().toString());
348                 }
349                 return null;
350             });
351 
352             Optional<Pair<String, String>> result = dialog.showAndWait();
353 
354             result.ifPresent(category -> {
355                 rowsCats.add(new Year.category(category.getKey(), category.getValue()));
356                 Platform.runLater(() -> refreshCmbx());
357 
358             });
359 
360 
361         }
362 
363     }
364 
365     private String catCmbxChanged(String newVal) {
366         final Year.category newCat = new Year.category("", "");
367         if (Objects.equals(newVal, "Add Category")) {
368             Dialog<Pair<String, String>> dialog = new Dialog<>();
369             dialog.setTitle("Add new category");
370 
371 // Set the button types.
372             ButtonType addCat = new ButtonType("Add", ButtonBar.ButtonData.OK_DONE);
373             dialog.getDialogPane().getButtonTypes().addAll(addCat, ButtonType.CANCEL);
374 
375 // Create the username and password labels and fields.
376             GridPane grid = new GridPane();
377             grid.setHgap(10);
378             grid.setVgap(10);
379             grid.setPadding(new Insets(20, 150, 10, 10));
380 
381             TextField catName = new TextField();
382             catName.setPromptText("Category Name");
383             DatePicker catDate = new DatePicker(LocalDate.now());
384             catDate.setPromptText("Category Due Date");
385 
386             grid.add(new Label("Category Name:"), 0, 0);
387             grid.add(catName, 1, 0);
388             grid.add(new Label("Category Due Date:"), 0, 1);
389             grid.add(catDate, 1, 1);
390 
391 
392 // Enable/Disable login button depending on whether a username was entered.
393             javafx.scene.Node addCatButton = dialog.getDialogPane().lookupButton(addCat);
394             addCatButton.setDisable(true);
395 
396 // Do some validation (using the Java 8 lambda syntax).
397             catName.textProperty().addListener((observable, oldValue, newValue) -> addCatButton.setDisable(newValue.trim().isEmpty()));
398 
399             dialog.getDialogPane().setContent(grid);
400 
401 // Request focus on the username field by default.
402             Platform.runLater(() -> catName.requestFocus());
403 
404 // Convert the result to a username-password-pair when the login button is clicked.
405             dialog.setResultConverter(dialogButton -> {
406                 if (dialogButton == addCat) {
407                     return new Pair<String, String>(catName.getText(), catDate.getValue().toString());
408                 }
409                 return null;
410             });
411 
412             Optional<Pair<String, String>> result = dialog.showAndWait();
413             result.ifPresent(category -> {
414                 newCat.catName = category.getKey();
415                 newCat.catDate = category.getValue();
416                 rowsCats.add(newCat);
417                 Platform.runLater(() -> refreshCmbx());
418 
419             });
420 
421 
422         }
423 
424         return newCat.catName;
425     }
426 
427     @FXML
428     private void addBtnPressed(ActionEvent event) {
429         int count = ProductTable.getItems().size() + 1;
430         data.add(new formattedProductProps(0, idTb.getText(), itemTb.getText(), sizeTb.getText(), new BigDecimal(rateTb.getText()), categoriesCmbx.getSelectionModel().getSelectedItem(), 0, BigDecimal.ZERO));
431         ProductTable.setItems(data);
432     }
433 
434     @FXML
435     private void submit(ActionEvent event) {
436         DbInt.getUserYears().forEach(year -> {
437             if (Objects.equals(year, yearText.getText())) {
438                 newYear = false;
439             }
440         });
441         if (chkboxCreateDatabase.isSelected() && newYear) {
442             CreateDb();
443         } else if (newYear) {
444             addYear();
445             updateDb(yearText.getText());
446         } else {
447             updateDb(yearText.getText());
448         }
449 
450         close();
451     }
452 
453     @FXML
454     private void cancel(ActionEvent event) {
455         close();
456     }
457 
458     private void close() {
459         Stage stage = (Stage) yearText.getScene().getWindow();
460         // do what you have to do
461         stage.close();
462     }
463 
464     public void initAddYear(Window parWindow) {
465         parentWindow = parWindow;
466         newYear = true;
467         chkboxCreateDatabase.setSelected(true);
468         yearText.setText(Integer.toString(Calendar.getInstance().get(Calendar.YEAR)));
469         categoriesTb.addAll("", "Add Category");
470         categoriesCmbx.getItems().setAll(categoriesTb);
471         String[][] columnNames = {{"ID", "productID"}, {"Item", "productName"}, {"Size", "productSize"}, {"Price/Item", "productUnitPriceString"}};
472         for (String[] column : columnNames) {
473             javafx.scene.control.TableColumn<formattedProductProps, String> tbCol = new javafx.scene.control.TableColumn<>(column[0]);
474             tbCol.setCellValueFactory(new PropertyValueFactory<>(column[1]));
475             tbCol.setCellFactory(TextFieldTableCell.forTableColumn());
476             ProductTable.getColumns().add(tbCol);
477         }
478         javafx.scene.control.TableColumn<formattedProductProps, String> categoryColumn = new javafx.scene.control.TableColumn<>("Category");
479         categoryColumn.setCellValueFactory(new PropertyValueFactory<>("productCategory"));
480 
481         categoryColumn.setCellFactory(ComboBoxTableCell.forTableColumn(categoriesTb));
482 
483         categoryColumn.setOnEditCommit(t -> {
484             String newVal = catCmbxChanged(t.getNewValue());
485 
486             t.getRowValue().productCategory.set(newVal);
487             data.get(t.getTablePosition().getRow()).productCategory.set(newVal);
488         });
489         ProductTable.getColumns().add(categoryColumn);
490         //{"Category", "productCategory"}
491 
492 
493         //categoryColumn.setCellEditor(new DefaultCellEditor(categoriesTb));
494 
495 
496     }
497 
498     /**
499      * Create the dialog.
500      */
501     public void initAddYear(String year, Window parWindow) {
502         newYear = false;
503         parentWindow = parWindow;
504         Year thisYear = new Year(year);
505         yearText.setText(year);
506         yearText.setEditable(false);
507 
508         categoriesCmbx.getItems().clear();
509         categoriesTb.clear();
510         categoriesTb.add("");
511         String browse = "Add Category";
512         thisYear.getCategories().forEach((category) -> {
513             categoriesTb.add(category.catName);
514             rowsCats.add(category);
515         });
516 
517         categoriesTb.add(browse);
518         categoriesCmbx.getItems().setAll(categoriesTb);
519         String[][] columnNames = {{"ID", "productID"}, {"Item", "productName"}, {"Size", "productSize"}, {"Price/Item", "productUnitPriceString"}};
520         for (String[] column : columnNames) {
521             javafx.scene.control.TableColumn<formattedProductProps, String> tbCol = new javafx.scene.control.TableColumn<>(column[0]);
522             tbCol.setCellValueFactory(new PropertyValueFactory<>(column[1]));
523             tbCol.setCellFactory(TextFieldTableCell.forTableColumn());
524             ProductTable.getColumns().add(tbCol);
525         }
526         javafx.scene.control.TableColumn<formattedProductProps, String> categoryColumn = new javafx.scene.control.TableColumn<>("Category");
527         categoryColumn.setCellValueFactory(new PropertyValueFactory<>("productCategory"));
528 
529         categoryColumn.setCellFactory(ComboBoxTableCell.forTableColumn(categoriesTb));
530 
531         categoryColumn.setOnEditCommit(t -> {
532             String newVal = catCmbxChanged(t.getNewValue());
533 
534             t.getRowValue().productCategory.set(newVal);
535             data.get(t.getTablePosition().getRow()).productCategory.set(newVal);
536 
537         });
538         ProductTable.getColumns().add(categoryColumn);
539         // boolean updateDb = true;
540         fillTable();
541 
542     }
543 
544     /*    public static void main(String... args) {
545             try {
546 
547                 Launchers.AddYear dialog = new Launchers.AddYear();
548                 dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
549                 dialog.setVisible(true);
550             } catch (RuntimeException e) {
551                 e.printStackTrace();
552             }
553         }*/
554     private void refreshCmbx() {
555         categoriesCmbx.getItems().clear();
556         categoriesTb.clear();
557         categoriesTb.add("");
558         String browse = "Add Category";
559 
560         rowsCats.forEach(cat -> categoriesTb.add(cat.catName));
561 
562 
563         categoriesTb.add(browse);
564         categoriesCmbx.getItems().setAll(categoriesTb);
565 
566     }
567 
568     /**
569      * Creates Database for the year specified.
570      */
571     private void CreateDb() {
572         Year yearToCreate = new Year(yearText.getText());
573         yearToCreate.CreateDb(ProductTable.getItems(), rowsCats);
574         ArrayList<String> years = DbInt.getUserYears();
575         ArrayList<String> usersManage = new ArrayList<>();
576         usersManage.add("");
577         years.add(yearText.getText());
578         Set<String> yearSet = new HashSet<>(years);
579 
580         User latestUser = new User(DbInt.getUserName(), "", usersManage, yearSet, true, 1);
581         if (!DbInt.getUserYears().isEmpty()) {
582             latestUser = new User(years.get(years.size() - 1));
583         }
584         latestUser.addToYear(yearText.getText());
585     }
586 
587     private void updateDb(String year) {
588         Year yearToUpdate = new Year(year);
589         yearToUpdate.updateDb(year, ProductTable.getItems(), rowsCats);
590     }
591 
592     private void addYear() {
593         Year yearToAdd = new Year(yearText.getText());
594         yearToAdd.addYear();
595     }
596 
597     /**
598      * Parses XML file to insert into products table on screen
599      *
600      * @param FLoc the location of the XML file
601      */
602     private void createTable(String FLoc) {
603         try {
604 
605             File fXmlFile = new File(FLoc);
606             DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
607             DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
608             Document doc = dBuilder.parse(fXmlFile);
609 
610             //optional, but recommended
611             //read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
612             doc.getDocumentElement().normalize();
613 
614             //System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
615             NodeList nListCats = doc.getElementsByTagName("Categories");
616 
617             // Collection<String[]> rowsCatsL = new ArrayList<>();
618 
619             for (int temp = 0; temp < nListCats.getLength(); temp++) {
620 
621                 Node nNode = nListCats.item(temp);
622 
623 
624                 if ((int) nNode.getNodeType() == (int) Node.ELEMENT_NODE) {
625 
626                     Element eElement = (Element) nNode;
627                     rowsCats.add(new Year.category(eElement.getElementsByTagName("CategoryName").item(0).getTextContent(), eElement.getElementsByTagName("CategoryDate").item(0).getTextContent()));
628                 }
629             }
630             //rowsCats = rowsCatsL;
631             NodeList nList = doc.getElementsByTagName("Products");
632 
633             Object[][] rows = new Object[nList.getLength()][5];
634 
635             for (int temp = 0; temp < nList.getLength(); temp++) {
636 
637                 Node nNode = nList.item(temp);
638 
639 
640                 if ((int) nNode.getNodeType() == (int) Node.ELEMENT_NODE) {
641 
642                     Element eElement = (Element) nNode;
643 
644 
645                     //String productID, String productName, String productSize, String productUnitPrice, String productCategory, int orderedQuantity, BigDecimal extendedCost
646                     formattedProductProps prodProps = new formattedProductProps(0, eElement.getElementsByTagName(
647                             "ProductID").item(0).getTextContent(),
648                             eElement.getElementsByTagName("ProductName").item(0).getTextContent(),
649                             eElement.getElementsByTagName("Size").item(0).getTextContent(),
650                             new BigDecimal(eElement.getElementsByTagName("UnitCost").item(0).getTextContent()),
651                             (eElement.getElementsByTagName("Category").item(0) != null) ? eElement.getElementsByTagName("Category").item(0).getTextContent() : "",
652                             0,
653                             BigDecimal.ZERO
654                     );
655                     data.add(prodProps);
656                     ProductTable.setItems(data);
657 
658                 }
659 
660 
661             }
662         } catch (Exception e) {
663             LogToFile.log(e, Severity.SEVERE, "Error Converting XML file to table. Please try again or contact support.");
664         }
665         refreshCmbx();
666     }
667 
668     /**
669      * Creates an XML file from the table
670      *
671      * @param SavePath Path to save the created XML file
672      */
673     private void createXML(String SavePath) {
674         try {
675             DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
676             DocumentBuilder docBuilder;
677 
678             docBuilder = docFactory.newDocumentBuilder();
679 
680 
681             // root elements
682             Document doc = docBuilder.newDocument();
683 
684             Element rootElement = doc.createElement("LawnGarden");
685             doc.appendChild(rootElement);
686             Iterable<Year.category> caters;
687             caters = rowsCats;
688             int[] i = {0};
689             //caters = getCategories(yearText.getText());
690             caters.forEach(cat -> {
691                         Element cats = doc.createElement("Categories");
692                         rootElement.appendChild(cats);
693                         Attr attr = doc.createAttribute("id");
694                         attr.setValue(Integer.toString(i[0]));
695                         cats.setAttributeNode(attr);
696 
697 
698                         //CateName elements
699                         Element ProductID = doc.createElement("CategoryName");
700                 ProductID.appendChild(doc.createTextNode(cat.catName));
701                         cats.appendChild(ProductID);
702 
703                         //CatDate elements
704                         Element ProductName = doc.createElement("CategoryDate");
705                 ProductName.appendChild(doc.createTextNode(cat.catDate));
706                         cats.appendChild(ProductName);
707                         i[0]++;
708                     }
709             );
710 
711             // staff elements
712 
713 
714             // set attribute to staff element
715             for (int i2 = 0; i2 < ProductTable.getItems().size(); i2++) {
716 
717                 Element staff = doc.createElement("Products");
718                 rootElement.appendChild(staff);
719                 Attr attr = doc.createAttribute("id");
720                 attr.setValue(Integer.toString(i2));
721                 staff.setAttributeNode(attr);
722 
723                 //ProductID elements
724                 Element ProductID = doc.createElement("ProductID");
725                 ProductID.appendChild(doc.createTextNode(ProductTable.getItems().get(i2).getProductID()));
726                 staff.appendChild(ProductID);
727 
728                 // Prodcut Name elements
729                 Element ProductName = doc.createElement("ProductName");
730                 ProductName.appendChild(doc.createTextNode(ProductTable.getItems().get(i2).getProductName()));
731                 staff.appendChild(ProductName);
732 
733                 // Unit COst elements
734                 Element UnitCost = doc.createElement("UnitCost");
735                 UnitCost.appendChild(doc.createTextNode(ProductTable.getItems().get(i2).getProductUnitPrice().toPlainString()));
736                 staff.appendChild(UnitCost);
737 
738                 // Size elements
739                 Element Size = doc.createElement("Size");
740                 Size.appendChild(doc.createTextNode(ProductTable.getItems().get(i2).getProductSize()));
741                 staff.appendChild(Size);
742 
743                 // Category elements
744 
745                 String cat = (ProductTable.getItems().get(i2).getProductCategory() != null) ? ProductTable.getItems().get(i2).getProductCategory() : "";
746                 Element category = doc.createElement("Category");
747                 category.appendChild(doc.createTextNode(cat));
748                 staff.appendChild(category);
749             }
750 
751 
752             // write the content into xml file
753             TransformerFactory transformerFactory = TransformerFactory.newInstance();
754             Transformer transformer = transformerFactory.newTransformer();
755             Source source = new DOMSource(doc);
756             Result result = new StreamResult(new FileOutputStream(SavePath));
757 
758             // Output to console for testing
759             // StreamResult result = new StreamResult(System.out);
760 
761             transformer.transform(source, result);
762 
763             //System.out.println("File saved!");
764         } catch (ParserConfigurationException e) {
765             LogToFile.log(e, Severity.SEVERE, "Error creating XML file: Parser error. Contact support.");
766         } catch (TransformerException e) {
767             LogToFile.log(e, Severity.SEVERE, "Error creating XML file: Parser Error. Contact support.");
768         } catch (FileNotFoundException e) {
769             LogToFile.log(e, Severity.SEVERE, "Error creating XML file: Error writing to file. Make sure the directory is readable by the software.");
770         }
771     }
772 
773     /**
774      * Fills the table from a DB table
775      */
776     private void fillTable() {
777         String year = yearText.getText();
778         Year yearInfo = new Year(year);
779 
780         formattedProduct[] productArray = yearInfo.getAllProducts();
781         Object[][] rows = new Object[productArray.length][6];
782         // data = FXCollections.observableArrayList();
783 
784         int i = 0;
785         for (formattedProduct productOrder : productArray) {
786             //String productID, String productName, String productSize, String productUnitPrice, String productCategory, int orderedQuantity, BigDecimal extendedCost
787             formattedProductProps prodProps = new formattedProductProps(productOrder.productKey, productOrder.productID, productOrder.productName, productOrder.productSize, productOrder.productUnitPrice, productOrder.productCategory, productOrder.orderedQuantity, productOrder.extendedCost);
788             data.add(prodProps);
789             i++;
790         }
791 
792         ProductTable.setItems(data);
793 
794     }
795 
796     @FXML
797     private void tablefromDb(ActionEvent event) {
798 
799         fillTable();
800     }
801 
802     @FXML
803     private void xmlFromTable(ActionEvent event) {
804         FileChooser chooser = new FileChooser();
805         FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("XML files", "*.xml", "*.XML");
806         chooser.getExtensionFilters().add(filter);
807         chooser.setSelectedExtensionFilter(filter);
808         File XML = chooser.showSaveDialog(parentWindow);
809         if (XML != null) {
810             String path = XML.getAbsolutePath();
811             if (!path.toLowerCase().endsWith(".xml")) {
812                 path += ".xml";
813             }
814             createXML(path);
815         }
816     }
817 
818 
819 }