PageRenderTime 221ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/ESSSetup/src/za/co/accsys/ess/FXMLDocumentController.java

https://gitlab.com/accsys/netbeansprojects
Java | 1128 lines | 728 code | 105 blank | 295 comment | 84 complexity | 04e7a9c05617d2bd9d13415c9981f351 MD5 | raw file
  1. /*
  2. * This is the Controller part of the MVC used to set up the PeopleWare organograms,
  3. * rules, and attributes.
  4. */
  5. package za.co.accsys.ess;
  6. import java.io.File;
  7. import java.io.FileWriter;
  8. import java.io.IOException;
  9. import java.net.URL;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.Collections;
  13. import java.util.Comparator;
  14. import java.util.Iterator;
  15. import java.util.LinkedList;
  16. import java.util.ResourceBundle;
  17. import java.util.StringTokenizer;
  18. import java.util.logging.Level;
  19. import java.util.logging.Logger;
  20. import javafx.application.Platform;
  21. import javafx.beans.property.DoubleProperty;
  22. import javafx.beans.property.SimpleDoubleProperty;
  23. import javafx.beans.value.ChangeListener;
  24. import javafx.beans.value.ObservableValue;
  25. import javafx.collections.FXCollections;
  26. import javafx.collections.ListChangeListener;
  27. import javafx.collections.ObservableList;
  28. import javafx.event.ActionEvent;
  29. import javafx.event.EventHandler;
  30. import javafx.fxml.FXML;
  31. import javafx.fxml.Initializable;
  32. import javafx.geometry.Insets;
  33. import javafx.scene.Node;
  34. import javafx.scene.control.Button;
  35. import javafx.scene.control.CheckBox;
  36. import javafx.scene.control.ChoiceBox;
  37. import javafx.scene.control.Dialogs;
  38. import javafx.scene.control.Dialogs.DialogResponse;
  39. import javafx.scene.control.Label;
  40. import javafx.scene.control.ListView;
  41. import javafx.scene.control.MenuItem;
  42. import javafx.scene.control.ProgressBar;
  43. import javafx.scene.control.SelectionMode;
  44. import javafx.scene.control.Tab;
  45. import javafx.scene.control.TabPane;
  46. import javafx.scene.control.TextField;
  47. import javafx.scene.control.Tooltip;
  48. import javafx.scene.control.TreeCell;
  49. import javafx.scene.control.TreeItem;
  50. import javafx.scene.control.TreeView;
  51. import javafx.scene.image.Image;
  52. import javafx.scene.image.ImageView;
  53. import javafx.scene.input.ClipboardContent;
  54. import javafx.scene.input.DataFormat;
  55. import javafx.scene.input.DragEvent;
  56. import javafx.scene.input.Dragboard;
  57. import javafx.scene.input.KeyCode;
  58. import javafx.scene.input.KeyEvent;
  59. import javafx.scene.input.MouseEvent;
  60. import javafx.scene.input.TransferMode;
  61. import javafx.scene.layout.Pane;
  62. import javafx.scene.layout.StackPane;
  63. import javafx.scene.paint.Color;
  64. import javafx.scene.text.Font;
  65. import javafx.scene.text.Text;
  66. import javafx.scene.web.HTMLEditor;
  67. import javafx.stage.FileChooser;
  68. import javafx.stage.Stage;
  69. import javafx.util.Callback;
  70. import static za.co.accsys.ess.ESSSetup.stage;
  71. import za.co.ucs.accsys.webmodule.ESSVersion;
  72. import za.co.ucs.accsys.webmodule.EmployeeSelection;
  73. import za.co.ucs.accsys.webmodule.EmployeeSelectionRule;
  74. import za.co.ucs.accsys.webmodule.FileContainer;
  75. import za.co.ucs.accsys.webmodule.ReportingStructure;
  76. import za.co.ucs.accsys.webmodule.SelectionInterpreter;
  77. import za.co.ucs.accsys.webmodule.SelectionLink;
  78. import za.co.ucs.accsys.webmodule.WebProcessDefinition;
  79. import za.co.ucs.lwt.initools.OutputFile;
  80. /**
  81. *
  82. * @author lterblanche
  83. */
  84. public class FXMLDocumentController implements Initializable {
  85. // Private members
  86. FileContainer fileContainer = FileContainer.getInstance();
  87. LinkedList<EmployeeSelection> localEmployeeSelections = new LinkedList<>();
  88. LinkedList<EmployeeSelection> llES_filteredEmployeeSelections = new LinkedList<>();
  89. LinkedList<EmployeeSelection> llRS_filteredAndUnusedEmployeeSelections = new LinkedList<>();
  90. LinkedList<ReportingStructure> llRS_ReportingStructures = new LinkedList<>();
  91. LinkedList<ReportingStructure> localReportingStructures = new LinkedList<>();
  92. LinkedList<WebProcessDefinition> localWebProcessDefinitions = new LinkedList<>();
  93. // Now add observability by wrapping it with ObservableList
  94. // ObservableList<ReportingStructure> observableReportingStructures = FXCollections.observableList(localReportingStructures);
  95. ObservableList<ReportingStructure> observableReportingStructures;
  96. // ObservableList<WebProcessDefinition> observableWebProcessDefinitions = FXCollections.observableList(localWebProcessDefinitions);
  97. ObservableList<WebProcessDefinition> observableWebProcessDefinitions;
  98. EmployeeSelection clipboardEmployeeSelection;
  99. SelectionLink clipboardSelectionLink;
  100. static boolean contentsChanged = false;
  101. static String appTitle = "ESS Configuration";
  102. // Used an observable value to bind to the progress bar (pbProgress)
  103. private final DoubleProperty progressBarPosition = new SimpleDoubleProperty(0);
  104. // <editor-fold defaultstate="collapsed" desc=" ${Scene Builder Setup} ">
  105. @FXML
  106. private TabPane tpTabPane;
  107. @FXML
  108. private Tab tabWebProcesses;
  109. @FXML
  110. private ListView<WebProcessDefinition> lvAvailableWebProcesses;
  111. @FXML
  112. private Label lblWebProcess_ProcessName;
  113. @FXML
  114. private TextField tfWebProcess_ProcessName;
  115. @FXML
  116. private Label lblWebProcess_ReportingStructure;
  117. @FXML
  118. private Label lblWebProcess_MaxProcAge;
  119. @FXML
  120. private Label lblWebProcess_MaxStageAge;
  121. @FXML
  122. private TextField tfWebProcess_MaxDurationPerProcess;
  123. @FXML
  124. private TextField tfWebProcess_MaxDurationPerStage;
  125. @FXML
  126. private CheckBox cbWebProcess_IsSupervisor;
  127. @FXML
  128. private Tab tabReportingStructures;
  129. @FXML
  130. private Tab tabSelectionFormulas;
  131. @FXML
  132. private TextField tfWebProcess_ActivateOn;
  133. @FXML
  134. private TextField tfWebProcess_DeactivateOn;
  135. @FXML
  136. private Button btnWebProcess_Apply;
  137. @FXML
  138. private CheckBox cbWebProcess_NotifyStaffOfActivation;
  139. @FXML
  140. private ChoiceBox<ReportingStructure> cbWebProcess_ReportingStructure;
  141. @FXML
  142. private CheckBox cbWebProcess_NotifyStaffOfDeActivation;
  143. @FXML
  144. private MenuItem mnuSaveConfiguration;
  145. @FXML
  146. private ListView<ReportingStructure> lvRS_ExistingReportingStructures;
  147. @FXML
  148. private ListView<EmployeeSelection> lvRS_ExistingEmployeeSelections;
  149. @FXML
  150. private Insets x1;
  151. @FXML
  152. private Button btnRS_ClearFilter;
  153. @FXML
  154. private TreeView<EmployeeSelection> tvRS_ReportingStructureTreeView;
  155. @FXML
  156. private TextField tfRS_FilterEmployeeSelections;
  157. private ListView<ReportingStructure> lvRS_FilteredEmployeeSelections;
  158. @FXML
  159. private TextField tfRS_FindEmployeeSelection;
  160. @FXML
  161. private Button btnRS_ClearLocate;
  162. @FXML
  163. private Insets x2;
  164. @FXML
  165. private Button btnRS_NewRS;
  166. @FXML
  167. private Button btnRS_RenameRS;
  168. @FXML
  169. private Button btnRS_CopyRS;
  170. @FXML
  171. private Button btnRS_DeleteRS;
  172. @FXML
  173. private MenuItem mnuClose;
  174. @FXML
  175. private TextField tfES_FilterEmployeeSelections;
  176. @FXML
  177. private Button btnES_ClearFilter;
  178. @FXML
  179. private Font x4;
  180. @FXML
  181. private HTMLEditor htmlSF_Editor;
  182. @FXML
  183. private ListView<EmployeeSelection> lvES_ExistingEmployeeSelections;
  184. @FXML
  185. private Button btnES_NewES;
  186. @FXML
  187. private Button btnES_DeleteES;
  188. @FXML
  189. private Button btnES_CopyES;
  190. @FXML
  191. private Button btnES_TestFormula;
  192. @FXML
  193. private Label lblRS_ReportingStructureHierarchy;
  194. @FXML
  195. private TextField tfES_ProcessName;
  196. @FXML
  197. private ChoiceBox<String> cbES_Filter;
  198. @FXML
  199. private ChoiceBox<String> cbES_Compare;
  200. @FXML
  201. private Button btnES_AddToFormula;
  202. @FXML
  203. private Button btnES_ApplyChanges;
  204. @FXML
  205. private ListView<String> lvES_TestResult;
  206. @FXML
  207. private MenuItem mnuValidateConfiguration;
  208. @FXML
  209. private Text txtStatus;
  210. @FXML
  211. private StackPane root;
  212. @FXML
  213. private MenuItem mnuExportConfiguration;
  214. @FXML
  215. private Color x3;
  216. @FXML
  217. private Font x5;
  218. @FXML
  219. private MenuItem mnuAbout;
  220. @FXML
  221. private Insets x11;
  222. @FXML
  223. private Insets x12;
  224. @FXML
  225. private Insets x13;
  226. @FXML
  227. private Insets x14;
  228. @FXML
  229. private Insets x15;
  230. @FXML
  231. private Insets x16;
  232. @FXML
  233. private Insets x17;
  234. @FXML
  235. private Insets x18;
  236. @FXML
  237. private ProgressBar pbProgress;
  238. // </editor-fold>
  239. //
  240. // <editor-fold defaultstate="collapsed" desc=" ${WebProcessDefinition Tab} ">
  241. /**
  242. * Setup the components used in the Web Process Definitions
  243. */
  244. private void initWebProcessDefinitionsTab() {
  245. // Populate existing WebProcessDefinitions
  246. lvAvailableWebProcesses.setItems(observableWebProcessDefinitions);
  247. //
  248. // EVENT LISTENER: Click on Web Proccesses Structure
  249. //
  250. lvAvailableWebProcesses.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<WebProcessDefinition>() {
  251. @Override
  252. public void changed(ObservableValue<? extends WebProcessDefinition> observable, WebProcessDefinition oldValue, WebProcessDefinition newValue) {
  253. // Update the display
  254. if (newValue != null) {
  255. tfWebProcess_ProcessName.setText(newValue.getName());
  256. tfWebProcess_MaxDurationPerProcess.setText(String.valueOf(newValue.getMaxProcessAge()));
  257. tfWebProcess_MaxDurationPerStage.setText(String.valueOf(newValue.getMaxStageAge()));
  258. tfWebProcess_ActivateOn.setText(String.valueOf(newValue.getActiveFromDayOfMonth()));
  259. tfWebProcess_DeactivateOn.setText(String.valueOf(newValue.getActiveToDayOfMonth()));
  260. cbWebProcess_NotifyStaffOfActivation.setSelected(newValue.isNotifyOfPendingActivation());
  261. cbWebProcess_NotifyStaffOfDeActivation.setSelected(newValue.isNotifyOfPendingDeactivation());
  262. cbWebProcess_IsSupervisor.setSelected(newValue.getCannotInstantiateSelf());
  263. // Populate the ChoiceBox with the list of available ReportingStructures
  264. cbWebProcess_ReportingStructure.setItems(observableReportingStructures);
  265. // Highlight the correct one
  266. cbWebProcess_ReportingStructure.getSelectionModel().clearSelection();
  267. if (newValue.getReportingStructure() != null) {
  268. cbWebProcess_ReportingStructure.getSelectionModel().select(newValue.getReportingStructure());
  269. }
  270. }
  271. }
  272. });
  273. //
  274. // EVENT LISTENER: Web Process Definition attributes changed
  275. //
  276. observableWebProcessDefinitions.addListener(new ListChangeListener() {
  277. @Override
  278. public void onChanged(ListChangeListener.Change change) {
  279. System.out.println("Web Process Definition - Detected a change! ");
  280. setContentsChanged(true);
  281. }
  282. });
  283. //
  284. // EVENT LISTENER: Click on Apply button
  285. //
  286. btnWebProcess_Apply.setOnAction(new EventHandler<ActionEvent>() {
  287. @Override
  288. public void handle(ActionEvent e) {
  289. int index = lvAvailableWebProcesses.getSelectionModel().getSelectedIndex();
  290. WebProcessDefinition toChange = localWebProcessDefinitions.get(index);
  291. saveWebProcessDefinition(toChange);
  292. observableWebProcessDefinitions.remove(toChange);
  293. observableWebProcessDefinitions.add(index, toChange);
  294. setContentsChanged(true);
  295. // Reselect in the listView
  296. lvAvailableWebProcesses.getSelectionModel().clearAndSelect(index);
  297. }
  298. });
  299. //
  300. // TOOL TIPS
  301. //
  302. Tooltip t1 = new Tooltip("This list contains all the possible processes that can be used in the ESS");
  303. Tooltip.install(lvAvailableWebProcesses, t1);
  304. Tooltip t2 = new Tooltip("When checked, the employee will not have access to this process.\n"
  305. + "Only a manager can use this process.\nAnd he/she can only use it on employees reporting to him/her.");
  306. Tooltip.install(cbWebProcess_IsSupervisor, t2);
  307. Tooltip t3a = new Tooltip("Should an employee be notified via email if this process is being activated?");
  308. Tooltip t3d = new Tooltip("Should an employee be notified via email if this process is being deactivated?");
  309. Tooltip.install(cbWebProcess_NotifyStaffOfActivation, t3a);
  310. Tooltip.install(cbWebProcess_NotifyStaffOfDeActivation, t3d);
  311. Tooltip t4 = new Tooltip("How many hours (8 hours per day) should a process stay alive before being cancelled?");
  312. Tooltip.install(tfWebProcess_MaxDurationPerProcess, t4);
  313. Tooltip t5 = new Tooltip("How long should a process wait for authorisation before escalating to the next person?");
  314. Tooltip.install(tfWebProcess_MaxDurationPerStage, t5);
  315. //
  316. // Select the first item
  317. //
  318. if (lvAvailableWebProcesses.getItems().size() > 0) {
  319. lvAvailableWebProcesses.getSelectionModel().select(0);
  320. }
  321. //
  322. // Bind the Progress Bar to the ProgressPosition variable
  323. //
  324. pbProgress.progressProperty().bind(progressBarPosition);
  325. }
  326. // </editor-fold>
  327. //
  328. // <editor-fold defaultstate="collapsed" desc=" ${ReportingStructure Tab} ">
  329. /**
  330. * Setup the components used in the Reporting Structures
  331. */
  332. private void initReportingStructuresTab() {
  333. // ----------------------------------------------
  334. // SETUP LISTVIEW : REPORTING STRUCTURES
  335. // Populate existing ReportingStructures
  336. lvRS_ExistingReportingStructures.setItems(observableReportingStructures);
  337. // Order the list
  338. orderReportingStructureList(lvRS_ExistingReportingStructures);
  339. // Disable the Delete button
  340. btnRS_DeleteRS.setDisable(true);
  341. // Disable the Rename button
  342. btnRS_RenameRS.setDisable(true);
  343. // Disable the Copy button
  344. btnRS_CopyRS.setDisable(true);
  345. //
  346. // EVENT LISTENER: Click Reporting Structure
  347. //
  348. lvRS_ExistingReportingStructures.setOnMouseClicked(new EventHandler<MouseEvent>() {
  349. @Override
  350. public void handle(MouseEvent event) {
  351. ReportingStructure newValue = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  352. if (newValue != null) {
  353. System.out.println("Selected item: " + newValue);
  354. // Enable the Delete button
  355. btnRS_DeleteRS.setDisable(false);
  356. // Enable the Rename button
  357. btnRS_RenameRS.setDisable(false);
  358. // Enable the Copy button
  359. btnRS_CopyRS.setDisable(false);
  360. // Clear the filters
  361. tfRS_FindEmployeeSelection.setText("");
  362. tfRS_FilterEmployeeSelections.setText("");
  363. buildReportingStructureInTreeView(newValue, tvRS_ReportingStructureTreeView);
  364. // For this reporting structure, list the
  365. // Employee Selections that has not yet been used, and
  366. // apply the filter (if any)
  367. rebuildEmployeeSelectionLists();
  368. }
  369. }
  370. });
  371. //
  372. // EVENT LISTENER: Reporting Structure List changed
  373. //
  374. observableReportingStructures.addListener(new ListChangeListener() {
  375. @Override
  376. public void onChanged(ListChangeListener.Change change) {
  377. System.out.println("Reporting Structures - Detected a change! " + change.toString());
  378. setContentsChanged(true);
  379. }
  380. });
  381. // ---------------------------------------------
  382. // SETUP LISTVIEW :EMPLOYEE SELECTIONS
  383. // FILTER Employee Selections
  384. //
  385. // Initiate the filtered list of EmployeeSelections
  386. llRS_filteredAndUnusedEmployeeSelections.addAll(localEmployeeSelections);
  387. lvRS_ExistingEmployeeSelections.setItems(FXCollections.observableList(llRS_filteredAndUnusedEmployeeSelections));
  388. // Order the list
  389. orderEmployeeSelectionList(lvRS_ExistingEmployeeSelections);
  390. //
  391. // EVENT LISTENER: Filter on TextField
  392. //
  393. tfRS_FilterEmployeeSelections.setOnKeyReleased(new EventHandler<KeyEvent>() {
  394. @Override
  395. public void handle(KeyEvent ke) {
  396. // Filter
  397. rebuildEmployeeSelectionLists();
  398. }
  399. });
  400. //
  401. // EVENT LISTENER: Click on Clear button
  402. //
  403. btnRS_ClearFilter.setOnAction(new EventHandler<ActionEvent>() {
  404. @Override
  405. public void handle(ActionEvent e) {
  406. tfRS_FilterEmployeeSelections.setText("");
  407. // Filter
  408. rebuildEmployeeSelectionLists();
  409. }
  410. });
  411. //
  412. // EVENT LISTENER: Click Employee Selection
  413. //
  414. lvRS_ExistingEmployeeSelections.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<EmployeeSelection>() {
  415. @Override
  416. public void changed(ObservableValue<? extends EmployeeSelection> observable, EmployeeSelection oldValue, EmployeeSelection newValue) {
  417. // This is where we build the reporting structure for the TreeView
  418. //System.out.println("Selected item: " + newValue);
  419. }
  420. });
  421. //
  422. // DRAG n DROP: On Drag Detected
  423. //
  424. lvRS_ExistingEmployeeSelections.setOnDragDetected(
  425. new EventHandler<MouseEvent>() {
  426. @Override
  427. public void handle(MouseEvent event
  428. ) {
  429. // Can't Drag if no Employee Selection is selected
  430. if (lvRS_ExistingEmployeeSelections.getSelectionModel().getSelectedItem() == null) {
  431. event.consume();
  432. return;
  433. }
  434. // Can't Drag if no Reporting Structure is selected
  435. if (lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem() == null) {
  436. event.consume();
  437. return;
  438. }
  439. /* drag was detected, start a drag-and-drop gesture*/
  440. /* allow any transfer mode */
  441. Dragboard db = lvRS_ExistingEmployeeSelections.startDragAndDrop(TransferMode.MOVE);
  442. /* Put a string on a dragboard */
  443. ClipboardContent content = new ClipboardContent();
  444. content.put(DataFormat.PLAIN_TEXT, lvRS_ExistingEmployeeSelections.getSelectionModel().getSelectedItem().toString());
  445. db.setContent(content);
  446. event.consume();
  447. }
  448. }
  449. );
  450. //
  451. // EVENT LISTENER: Delete Reporting Structure
  452. //
  453. btnRS_DeleteRS.setOnAction(
  454. new EventHandler<ActionEvent>() {
  455. @Override
  456. public void handle(ActionEvent e) {
  457. ReportingStructure selected = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  458. if (selected != null) {
  459. DialogResponse response = Dialogs.showConfirmDialog(null,
  460. "Do you wish to delete this reporting structure?", "Confirm Deletion", "Delete '" + selected + "'", Dialogs.DialogOptions.YES_NO);
  461. if (response == DialogResponse.YES) {
  462. // Clear this Reporting Structure
  463. //lvRS_ExistingReportingStructures.getItems().remove(selected);
  464. observableReportingStructures.remove(selected);
  465. // Unselect reporting structures
  466. //lvRS_ExistingReportingStructures.getSelectionModel().clearSelection();
  467. // Clear TreeView
  468. tvRS_ReportingStructureTreeView.setRoot(null);
  469. //TODO: Still clear up the WebProcessDefinition screen if the reporting structure is gone
  470. //rebuildReportingStructureLists();
  471. setContentsChanged(true);
  472. }
  473. }
  474. }
  475. }
  476. );
  477. //
  478. // EVENT LISTENER: Rename Reporting Structure
  479. //
  480. btnRS_RenameRS.setOnAction(
  481. new EventHandler<ActionEvent>() {
  482. @Override
  483. public void handle(ActionEvent e) {
  484. ReportingStructure selected = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  485. if (selected != null) {
  486. String newName = Dialogs.showInputDialog(null, "New name:", "Rename Reporting Structure", "Rename '" + selected + "'", selected.getName());
  487. if (newName != null) {
  488. if (newName.trim().length() > 0) {
  489. // Rename Reporting Structure
  490. int index = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedIndex();
  491. ReportingStructure toChange = localReportingStructures.get(index);
  492. String originalName = toChange.toString();
  493. observableReportingStructures.remove(toChange);
  494. toChange.setName(newName);
  495. //
  496. // Validate new name
  497. //
  498. while (!isRSNameUnique(toChange)) {
  499. String nameOfCurrentStructure = toChange.getName();
  500. String message = "Please rename:\n\n\t" + nameOfCurrentStructure + "\n\nto avoid errors in the reporting structure.";
  501. String newStructureName = Dialogs.showInputDialog(getMainStage(), message, "The name already exists!", "Duplicate name", nameOfCurrentStructure);
  502. // If the suer makes it blank keep the old name
  503. if (newStructureName == null || newStructureName.trim().length() == 0) {
  504. newStructureName = originalName;
  505. }
  506. toChange.setName(newStructureName);
  507. setContentsChanged(true);
  508. }
  509. showStatus(null, 0, 0);
  510. if (toChange.getName() != null) {
  511. observableReportingStructures.add(index, toChange);
  512. }
  513. // Order the list
  514. orderReportingStructureList(lvRS_ExistingReportingStructures);
  515. orderEmployeeSelectionList(lvRS_ExistingEmployeeSelections);
  516. // Once created and added, select it
  517. lvRS_ExistingReportingStructures.getSelectionModel().select(toChange);
  518. lvRS_ExistingReportingStructures.scrollTo(lvRS_ExistingReportingStructures.getSelectionModel().getSelectedIndex());
  519. }
  520. }
  521. }
  522. }
  523. }
  524. );
  525. //
  526. // EVENT LISTENER: New Reporting Structure
  527. //
  528. btnRS_NewRS.setOnAction(
  529. new EventHandler<ActionEvent>() {
  530. @Override
  531. public void handle(ActionEvent e) {
  532. String newName = Dialogs.showInputDialog(null, "Name:", "Create a new Reporting Structure", "New Reporting Structure");
  533. if (newName != null) {
  534. if (newName.trim().length() > 0) {
  535. // New Reporting Structure
  536. ReportingStructure newStructure = new ReportingStructure(newName, newName);
  537. setContentsChanged(true);
  538. //
  539. // Validate new name
  540. //
  541. int i = 1;
  542. while (!isRSNameUnique(newStructure)) {
  543. String nameOfCurrentStructure = newStructure.getName();
  544. String message = "Please rename:\n\n\t" + nameOfCurrentStructure + "\n\nto avoid errors in the reporting structure.\n*Failure to choose a unique name will result in an automatic rename.";
  545. String newStructureName = Dialogs.showInputDialog(getMainStage(), message, "The name already exists!", "Duplicate name", nameOfCurrentStructure);
  546. // If the user cancels exit the loop
  547. if (newStructureName == null) {
  548. return;
  549. }
  550. // If the user makes it blank rename
  551. if (newStructureName.trim().length() == 0) {
  552. newStructureName = i++ + "_renamed_" + nameOfCurrentStructure;
  553. }
  554. newStructure.setName(newStructureName);
  555. setContentsChanged(true);
  556. }
  557. showStatus(null, 0, 0);
  558. if (newStructure.getName() != null) {
  559. observableReportingStructures.add(newStructure);
  560. }
  561. // Order the list
  562. orderReportingStructureList(lvRS_ExistingReportingStructures);
  563. orderEmployeeSelectionList(lvRS_ExistingEmployeeSelections);
  564. // Once created and added, select it
  565. lvRS_ExistingReportingStructures.getSelectionModel().select(newStructure);
  566. lvRS_ExistingReportingStructures.scrollTo(lvRS_ExistingReportingStructures.getSelectionModel().getSelectedIndex());
  567. }
  568. }
  569. }
  570. }
  571. );
  572. //
  573. // EVENT LISTENER: Copy Reporting Structure
  574. //
  575. btnRS_CopyRS.setOnAction(
  576. new EventHandler<ActionEvent>() {
  577. @Override
  578. public void handle(ActionEvent e) {
  579. ReportingStructure toCopy = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  580. if (toCopy != null) {
  581. String newName = Dialogs.showInputDialog(null, "Name for new Reporting Structure", "Copy", "Copy existing Reporting Structure", toCopy.getName() + "(copy)");
  582. if (newName != null) {
  583. if (newName.trim().length() > 0) {
  584. // Rename Reporting Structure
  585. ReportingStructure newStructure = new ReportingStructure(newName, newName);
  586. LinkedList<SelectionLink> links = new LinkedList(toCopy.selectionLinks);
  587. for (SelectionLink sl : links) {
  588. newStructure.addSelectionLink(sl);
  589. }
  590. //
  591. // Validate new name
  592. //
  593. int nbReportingStructures = localReportingStructures.size();
  594. if (nbReportingStructures > 0) {
  595. int i = 1;
  596. showStatus("Testing Reporting Structure: " + newStructure.toString(), i + 1, nbReportingStructures);
  597. //
  598. // Check that names differ
  599. //
  600. LinkedList<ReportingStructure> localStructures = new LinkedList(localReportingStructures);
  601. // localStructures.remove(newStructure);
  602. for (ReportingStructure structureInList : localStructures) {
  603. // If hashCodes are the same rename the current reporting structure
  604. if (newStructure.getName().equals(structureInList.getName())) {
  605. // Ask user to change name
  606. // Edit a Reporting Structure
  607. // Edit dialog
  608. String nameOfCurrentStructure = newStructure.getName();
  609. String message = "Please rename:\n\n\t" + nameOfCurrentStructure + "\n\nto avoid errors in the reporting structure.\n\n*If you do not rename the reporting structure it will be renamed automatically.";
  610. String newStructureName = Dialogs.showInputDialog(getMainStage(), message, "The name already exists!", "Duplicate name");
  611. // Rename Structure
  612. if ((newStructureName == null) || (newStructureName.trim().length() == 0)) {
  613. newStructureName = i - 1 + "_renamed_" + nameOfCurrentStructure;
  614. }
  615. newStructure.setName(newStructureName);
  616. setContentsChanged(true);
  617. }
  618. i++;
  619. }
  620. showStatus(null, 0, 0);
  621. }
  622. // Add to existing list
  623. observableReportingStructures.add(newStructure);
  624. // Order the list
  625. orderReportingStructureList(lvRS_ExistingReportingStructures);
  626. orderEmployeeSelectionList(lvRS_ExistingEmployeeSelections);
  627. rebuildEmployeeSelectionLists();
  628. // Once created and added, select it
  629. lvRS_ExistingReportingStructures.getSelectionModel().select(newStructure);
  630. lvRS_ExistingReportingStructures.scrollTo(lvRS_ExistingReportingStructures.getSelectionModel().getSelectedIndex());
  631. setContentsChanged(true);
  632. }
  633. }
  634. } else {
  635. Dialogs.showErrorDialog(null, "Please select an existing Reporting Structure before trying to copy it.");
  636. }
  637. }
  638. }
  639. );
  640. // --------------------------------------
  641. // SETUP TREEVIEW: Reporting Structures
  642. // CELL FACTORY for TreeView
  643. //
  644. tvRS_ReportingStructureTreeView.setCellFactory(
  645. new Callback<TreeView<EmployeeSelection>, TreeCell<EmployeeSelection>>() {
  646. @Override
  647. public TreeCell call(TreeView<EmployeeSelection> param
  648. ) {
  649. return new DnDCell(param, lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem());
  650. }
  651. }
  652. );
  653. //
  654. // EVENT LISTENER: Person typed in search terms
  655. //
  656. tfRS_FindEmployeeSelection.setOnKeyReleased(
  657. new EventHandler<KeyEvent>() {
  658. @Override
  659. public void handle(KeyEvent ke
  660. ) {
  661. // Only SEARCH if we have selected a Reporting Structure
  662. if (tvRS_ReportingStructureTreeView.getRoot() != null) {
  663. TreeItem rootItem = tvRS_ReportingStructureTreeView.getRoot();
  664. TreeItem selectedItem = rootItem;
  665. // GET FILTER String
  666. String strFind = tfRS_FindEmployeeSelection.getText();
  667. if (strFind.trim().length() > 0) {
  668. //Locate strFind in the TreeView
  669. selectedItem = searchInTreeView(rootItem, strFind);
  670. }
  671. // Only highlight found item if we did, in fact, find an item
  672. if (selectedItem != null) {
  673. tvRS_ReportingStructureTreeView.getSelectionModel().select(selectedItem);
  674. tvRS_ReportingStructureTreeView.scrollTo(tvRS_ReportingStructureTreeView.getRow(selectedItem));
  675. }
  676. }
  677. }
  678. /**
  679. * Iteratively steps through the tree view, looking for the first
  680. * occurrence of 'searchString' in the given TreeItem
  681. *
  682. * @param currentNode
  683. * @param valueToSearch
  684. * @return TreeItem - the item that matches the search string
  685. */
  686. private TreeItem<EmployeeSelection> searchInTreeView(final TreeItem<EmployeeSelection> currentNode, final String valueToSearch) {
  687. TreeItem<EmployeeSelection> result = null;
  688. if (matchesFilter(currentNode.toString(), valueToSearch)) {
  689. result = currentNode;
  690. } else if (!currentNode.isLeaf()) {
  691. for (TreeItem<EmployeeSelection> child : currentNode.getChildren()) {
  692. result = searchInTreeView(child, valueToSearch);
  693. if (result != null) {
  694. break;
  695. }
  696. }
  697. }
  698. return result;
  699. }
  700. }
  701. );
  702. //
  703. // EVENT LISTENER: Person pressed a KEY
  704. //
  705. tvRS_ReportingStructureTreeView.setOnKeyPressed(new EventHandler<KeyEvent>() {
  706. @Override
  707. public void handle(KeyEvent t) {
  708. System.out.println("KeyCode :" + t.getCode());
  709. //
  710. // KEY = DELETE
  711. //
  712. if (t.getCode() == KeyCode.DELETE) {
  713. // Which item was deleted?
  714. TreeItem<EmployeeSelection> ti = tvRS_ReportingStructureTreeView.getSelectionModel().getSelectedItem();
  715. EmployeeSelection es = ti.getValue();
  716. ReportingStructure rs = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  717. deleteEmployeeSelectionFromReportingStructure(es, rs);
  718. buildReportingStructureInTreeView(rs, tvRS_ReportingStructureTreeView);
  719. // For this reporting structure, list the
  720. // Employee Selections that has not yet been used, and
  721. // apply the filter (if any)
  722. rebuildEmployeeSelectionLists();
  723. tvRS_ReportingStructureTreeView.getSelectionModel().clearSelection();
  724. setContentsChanged(true);
  725. t.consume();
  726. }
  727. //
  728. // KEY = CTRL+X (Cut)
  729. //
  730. if (t.getCode().equals(KeyCode.X) && t.isControlDown()) {
  731. System.out.println("Cut :" + t.getCode());
  732. // Which EmployeeSelection was cut?
  733. TreeItem<EmployeeSelection> ti = tvRS_ReportingStructureTreeView.getSelectionModel().getSelectedItem();
  734. int selectionIndex = tvRS_ReportingStructureTreeView.getSelectionModel().getSelectedIndex();
  735. EmployeeSelection es = ti.getValue();
  736. clipboardEmployeeSelection = es;
  737. // Which SelectionLink should be cut?
  738. ReportingStructure rs = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  739. EmployeeSelection parentSelection = rs.getParentSelection(clipboardEmployeeSelection);
  740. clipboardSelectionLink = rs.getSelectionLink(clipboardEmployeeSelection, parentSelection);
  741. buildReportingStructureInTreeView(rs, tvRS_ReportingStructureTreeView);
  742. tvRS_ReportingStructureTreeView.getSelectionModel().select(selectionIndex);
  743. tvRS_ReportingStructureTreeView.scrollTo(selectionIndex);
  744. t.consume();
  745. }
  746. //
  747. // KEY = CTRL+V (Paste)
  748. //
  749. if (t.getCode().equals(KeyCode.V) && t.isControlDown()) {
  750. System.out.println("Paste :" + t.getCode());
  751. // Which item was selected?
  752. ReportingStructure rs = lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem();
  753. TreeItem<EmployeeSelection> ti = tvRS_ReportingStructureTreeView.getSelectionModel().getSelectedItem();
  754. EmployeeSelection newParentSelection = ti.getValue();
  755. //
  756. // ONLY PASTE IF ITS NOT RECURSIVE!
  757. //
  758. if (isDecendentOf(tvRS_ReportingStructureTreeView, clipboardEmployeeSelection.toString(), newParentSelection.toString())) // We accept the transfer!!!!!
  759. {
  760. Dialogs.showErrorDialog(null, "You cannot paste an Employee Selection under a Selection that reports to it.");
  761. // Reset the 'clipboardEmployeeSelection'
  762. clipboardEmployeeSelection = null;
  763. buildReportingStructureInTreeView(rs, tvRS_ReportingStructureTreeView);
  764. t.consume();
  765. } else {
  766. // Delete the CUT selection link
  767. rs.getSelectionLinks().remove(clipboardSelectionLink);
  768. // Create the PASTE selection link
  769. SelectionLink pasteLink = new SelectionLink(clipboardEmployeeSelection, newParentSelection);
  770. int selectionIndex = tvRS_ReportingStructureTreeView.getSelectionModel().getSelectedIndex();
  771. rs.getSelectionLinks().add(pasteLink);
  772. // Reset the 'clipboardEmployeeSelection'
  773. clipboardEmployeeSelection = null;
  774. buildReportingStructureInTreeView(rs, tvRS_ReportingStructureTreeView);
  775. tvRS_ReportingStructureTreeView.getSelectionModel().select(selectionIndex);
  776. tvRS_ReportingStructureTreeView.scrollTo(selectionIndex);
  777. setContentsChanged(true);
  778. t.consume();
  779. }
  780. }
  781. }
  782. });
  783. //
  784. // EVENT LISTENER: Select an item in the TreeView
  785. //
  786. tvRS_ReportingStructureTreeView.getSelectionModel()
  787. .selectedItemProperty().addListener(new ChangeListener() {
  788. @Override
  789. public void changed(ObservableValue observable, Object oldValue,
  790. Object newValue
  791. ) {
  792. TreeItem<EmployeeSelection> selectedItem = (TreeItem<EmployeeSelection>) newValue;
  793. if (selectedItem != null) {
  794. System.out.println("Selected Text : " + selectedItem.getValue());
  795. //Display the hierarchy from this selection to the top
  796. lblRS_ReportingStructureHierarchy.setText(getHierarchyOfReportingStructure(lvRS_ExistingReportingStructures.getSelectionModel().getSelectedItem(), selectedItem.getValue()));
  797. }
  798. }
  799. }
  800. );
  801. }
  802. // </editor-fold>
  803. //
  804. // <editor-fold defaultstate="collapsed" desc=" ${EmployeeSelections Tab} ">
  805. /**
  806. * Setup the components used in the Web Process Definitions
  807. */
  808. private void initEmployeeSelectionsTab() {
  809. // ---------------------------------------------
  810. // SETUP LISTVIEW :EMPLOYEE SELECTIONS
  811. // FILTER Employee Selections
  812. //
  813. // Initiate the filtered list of EmployeeSelections
  814. llES_filteredEmployeeSelections.addAll(localEmployeeSelections);
  815. lvES_ExistingEmployeeSelections.setItems(FXCollections.observableList(llES_filteredEmployeeSelections));
  816. // Order the list
  817. orderEmployeeSelectionList(lvES_ExistingEmployeeSelections);
  818. lvES_ExistingEmployeeSelections.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
  819. // ---------------------------------------------
  820. // SETUP HTML Editor
  821. // HIDE Controls
  822. //
  823. // for (Node toolBar = htmlSF_Editor.lookup(".tool-bar"); toolBar != null; toolBar = htmlSF_Editor.lookup(".tool-bar")) {
  824. // ((Pane) toolBar.getParent()).getChildren().remove(toolBar);
  825. // }
  826. //
  827. // SETUP CHOICEBOX: Filter
  828. //
  829. // Populate the ChoiceBox with the list of available Filters
  830. ArrayList<String> keyWords = new ArrayList<>();
  831. keyWords.addAll(Arrays.asList(EmployeeSelectionRule.getKeyWords()));
  832. cbES_Filter.setItems(FXCollections.observableList(keyWords));
  833. //
  834. // SETUP CHOICEBOX: Comparitors
  835. //
  836. // Populate the ChoiceBox with the list of available Filters
  837. ArrayList<String> comparitors = new ArrayList<>();
  838. comparitors.addAll(Arrays.asList(getSelectionComparators()));
  839. cbES_Compare.setItems(FXCollections.observableList(comparitors));
  840. //
  841. // Disable all the buttons
  842. //
  843. // <editor-fold defaultstate="collapsed" desc=" $Disable all the buttons ">
  844. {
  845. // Disable the Delete button
  846. btnES_DeleteES.setDisable(true);
  847. // Disable the Copy button
  848. btnES_CopyES.setDisable(true);
  849. // Disable Test Formula Button
  850. btnES_TestFormula.setDisable(true);
  851. // Disable the AddToFormula button
  852. btnES_AddToFormula.setDisable(true);
  853. // Disable dropdown choicebox for Filter
  854. cbES_Filter.setDisable(true);
  855. // Disable dropdown choicebox for Compare
  856. cbES_Compare.setDisable(true);
  857. // Disable Apply Changes
  858. btnES_ApplyChanges.setDisable(true);
  859. }
  860. // </editor-fold>
  861. //
  862. // EVENT LISTENER: On Test Formula
  863. //
  864. btnES_TestFormula.setOnAction(new EventHandler<ActionEvent>() {
  865. @Override
  866. public void handle(ActionEvent e) {
  867. // Get the text in the HTMLEditor
  868. String htmlText = htmlSF_Editor.getHtmlText();
  869. String plainText = stripHTML(htmlText);
  870. plainText = plainText.replaceAll("&nbsp;", " ");
  871. plainText = plainText.replaceAll("&NBSP;", " ");
  872. // Display the formula
  873. htmlSF_Editor.setHtmlText(convertStringToHTML(plainText));
  874. //-------------------
  875. // Evaluate the rule
  876. //-------------------
  877. // Create a new Rule and Execute it to test the results
  878. EmployeeSelectionRule rule = new EmployeeSelectionRule("Test", "Test");
  879. // Extract Text from editor and execute rule
  880. rule.setRule(plainText);
  881. String testResult = rule.listResult();
  882. StringTokenizer token = new StringTokenizer(testResult, "\n");
  883. ObservableList<String> items = FXCollections.observableArrayList();
  884. while (token.hasMoreTokens()) {
  885. String resultEmp = token.nextToken();
  886. items.add(resultEmp);
  887. }
  888. lvES_TestResult.setItems(items);
  889. // Enable the Apply button
  890. btnES_ApplyChanges.setDisable(false);
  891. }
  892. });
  893. //
  894. // EVENT LISTENER: On AddToFormula
  895. //
  896. btnES_AddToFormula.setOnAction(new EventHandler<ActionEvent>() {
  897. @Override
  898. public void handle(ActionEvent event) {
  899. // Add a default formula into the Rules Editor
  900. String comparator = cbES_Compare.getSelectionModel().getSelectedItem();
  901. String formula = " [" + cbES_Filter.getSelectionModel().getSelectedItem() + " " + comparator + " '...'] ";
  902. String htmlText = htmlSF_Editor.getHtmlText();
  903. String text = htmlText.replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " ");
  904. text = text.replaceAll("&nbsp;", " ");
  905. text = text + formula;
  906. // Display the formula
  907. htmlSF_Editor.setHtmlText(convertStringToHTML(text));
  908. }
  909. });
  910. //
  911. // EVENT LISTENER: Filter on TextField
  912. //
  913. tfES_FilterEmployeeSelections.setOnKeyReleased(new EventHandler<KeyEvent>() {
  914. @Override
  915. public void handle(KeyEvent ke) {
  916. // Filter
  917. rebuildEmployeeSelectionLists();
  918. }
  919. });
  920. //
  921. // EVENT LISTENER: Change on Selection's name
  922. //
  923. tfES_ProcessName.setOnKeyReleased(new EventHandler<KeyEvent>() {
  924. @Override
  925. public void handle(KeyEvent ke) {
  926. // Enable the Apply button
  927. btnES_ApplyChanges.setDisable(false);
  928. }
  929. });
  930. //
  931. // EVENT LISTENER: Click on Clear button
  932. //
  933. btnES_ClearFilter.setOnAction(new EventHandler<ActionEvent>() {
  934. @Override
  935. public void handle(ActionEvent e) {
  936. tfES_FilterEmployeeSelections.setText("");
  937. // Filter
  938. rebuildEmployeeSelectionLists();
  939. }
  940. });
  941. //
  942. // EVENT LISTENER: Click Employee Selection
  943. //
  944. lvES_ExistingEmployeeSelections.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<EmployeeSelection>() {
  945. @Override
  946. public void changed(ObservableValue<? extends EmployeeSelection> observable, EmployeeSelection oldValue, EmployeeSelection newValue) {
  947. if (newValue != null) {
  948. // This is where we build the reporting structure for the TreeView
  949. System.out.println("Selected EmployeeSelection item: " + newValue);
  950. // Enable the Delete button
  951. btnES_DeleteES.setDisable(false);
  952. // Enable the Copy button
  953. btnES_CopyES.setDisable(false);
  954. // Enable Test Formula Button
  955. btnES_TestFormula.setDisable(false);
  956. // Enable the AddToFormula button
  957. btnES_AddToFormula.setDisable(false);
  958. // Enable dropdown choicebox for Filter
  959. cbES_Filter.setDisable(false);
  960. // Enable dropdown choicebox for Compare
  961. cbES_Compare.setDisable(false);
  962. // Display the formula
  963. htmlSF_Editor.setHtmlText(convertStringToHTML(((EmployeeSelectionRule) newValue).getRule()));
  964. // Display the name
  965. tfES_ProcessName.setText(((EmployeeSelection) newValue).getName());
  966. }
  967. }
  968. });
  969. //
  970. // EVENT LISTENER: Delete Employee Selection
  971. //
  972. btnES_DeleteES.setOnAction(
  973. new EventHandler<ActionEvent>() {
  974. @Override
  975. public void handle(ActionEvent e) {
  976. // Did we select multiple items?
  977. EmployeeSelection selected = lvES_ExistingEmployeeSelections.getSelectionModel().getSelectedItem();
  978. deleteEmployeeSelectionFromCollection(lvES_ExistingEmployeeSelections.getSelectionModel().getSelectedItems());
  979. }
  980. }
  981. );
  982. //
  983. // EVENT LISTENER: Person pressed the DELETE button
  984. //
  985. lvES_ExistingEmployeeSelections.setOnKeyPressed(new EventHandler<KeyEvent>() {
  986. @Override
  987. public void handle(KeyEvent t) {
  988. if (t.getCode() == KeyCode.DELETE) {
  989. EmployeeSelection selected = lvES_ExistingEmployeeSelections.getSelectionModel().getSelectedItem();
  990. deleteEmployeeSelectionFromCollection(lvES_ExistingEmployeeSelections.getSelectionModel().getSelectedItems());
  991. t.consume();
  992. }
  993. }
  994. });
  995. //
  996. // EVENT LISTENER: Click on NEW (New Employee Selection)
  997. //
  998. btnES_NewES.setOnAction(
  999. new EventHandler<ActionEvent>() {
  1000. @Override
  1001. public void handle(ActionEvent e) {
  1002. String newName = Dialogs.showInputDialog(null, "Name:", "Create a new Employee Selection", "New Employee Selection");
  1003. if (newName != null) {
  1004. if (newName.trim().length() > 0) {
  1005. // New employee Selection
  1006. EmployeeSelection newSelection = new EmployeeSelectionRule(newName, newName);
  1007. //
  1008. // Validate new name
  1009. //
  1010. int nbEmployeeSelections = localEmployeeSelections.size();
  1011. if (nbEmployeeSelections > 0) {
  1012. int i = 1;
  1013. showStatus("Testing Employee Selection: " + newSelection.toString(), i + 1, nbEmployeeSelections);
  1014. //
  1015. // Check that names differ
  1016. //
  1017. LinkedList<EmployeeSelection> localSelections = new LinkedList(localEmployeeSelections);
  1018. for (EmployeeSelection selectionInList : localSelections) {
  1019. // If hashCodes are the same rename the current reporting structure
  1020. if (newSelection.hashCode() == selectionInList.hashCode()) {
  1021. // Ask user to change name
  1022. // Edit a Reporting Structure
  1023. // Edit dialog