OTX-Runtime for Java  
Runtime API Sample Program

The Sample program demonstrates the main functionality of the OTX-Runtime API. It can be used as a reference for the expected runtime behavior of the API and the source code below is like a reference guide about the proper programming of the API.

The OpenTestSystem.Otx.Runtime2.Api.ReferenceApplication.Java.jar only runs directly with java from version 1.8 to version 10. From java 11, JavaFX and JAXB are no longer included in the JDK. Please download JavaFX (here) and JAXB (here), unzip their content in the execution folder.

Note: In the execution folder, the JavaFX libs must be stored in the folder with name 'javafx', and the JAXB libs in the folder with name 'jaxb-ri'.

Code Example

Code snippet of the OTX-Runtime API Sample Program.

1 package OpenTestSystem.Otx.Runtime.Api.Sample;
2 
11 import OpenTestSystem.Otx.Runtime.Api.Sample.OutputCustomImplementation.*;
12 import OpenTestSystem.Otx.Runtime.Api.Sample.Setting.SaveSettingUtil;
14 import javafx.application.HostServices;
15 import javafx.application.Platform;
16 import javafx.beans.property.SimpleStringProperty;
17 import javafx.beans.value.ObservableValue;
18 import javafx.collections.FXCollections;
19 import javafx.collections.ObservableList;
20 import javafx.event.ActionEvent;
21 import javafx.fxml.FXML;
22 import javafx.fxml.FXMLLoader;
23 import javafx.scene.Node;
24 import javafx.scene.Scene;
25 import javafx.scene.control.Button;
26 import javafx.scene.control.Label;
27 import javafx.scene.control.TextField;
28 import javafx.scene.control.*;
29 import javafx.scene.control.cell.PropertyValueFactory;
30 import javafx.scene.control.cell.TextFieldTableCell;
31 import javafx.scene.image.Image;
32 import javafx.scene.image.ImageView;
33 import javafx.scene.input.Clipboard;
34 import javafx.scene.input.ClipboardContent;
35 import javafx.scene.input.MouseEvent;
36 import javafx.stage.*;
37 
38 import javax.crypto.BadPaddingException;
39 import javax.crypto.IllegalBlockSizeException;
40 import javax.crypto.NoSuchPaddingException;
41 import javax.swing.plaf.synth.SynthTextAreaUI;
42 import java.awt.*;
43 import java.awt.event.ComponentAdapter;
44 import java.awt.event.ComponentEvent;
45 import java.awt.event.WindowEvent;
46 import java.awt.event.WindowListener;
47 import java.io.File;
48 import java.io.IOException;
49 import java.net.URL;
50 import java.nio.file.Files;
51 import java.nio.file.Path;
52 import java.nio.file.Paths;
53 import java.security.InvalidAlgorithmParameterException;
54 import java.security.InvalidKeyException;
55 import java.security.NoSuchAlgorithmException;
56 import java.time.LocalDateTime;
57 import java.time.format.DateTimeFormatter;
58 import java.util.List;
59 import java.util.*;
60 import java.util.stream.Collectors;
61 
62 public class SampleForm {
63  //region Constants
64  static HostServices hostServices;
65  // TODO: consider moving to somewhere else
66  private static final String PROJECT_ICON = "/ODFProject.bmp";
67  private static final String DOCUMENT_ICON = "/DocumentOTX16.bmp";
68  private static final String PROCEDURE_ICON = "/Procedure.bmp";
69  private static final String PACKAGE_ICON = "/Procedure.bmp";
70 
71  private static final String SOCKET_COMMUNICATION = "SOCKET";
72  private static final String DEFAULT_RUNTIME_PORT = "0";
73  private static final String DEFAULT_DIAG_MANAGER_PORT = "8888";
74 
75  private static final String PIPE_COMMUNICATION = "PIPE";
76  private static final String DEFAULT_RUNTIME_PIPE_NAME = "Emotive";
77  private static final String DEFAULT_DIAG_MANAGER_PIPE_NAME = "DiagManager";
78 
79  private static final String PTX_EXTENSION = "ptx";
80  private static final String PPX_EXTENSION = "ppx";
81 
82  private static final int DEFAULT_POLLING_TIME = 500;
83  private static final int DEFAULT_BATTERY_VOLTAGE_THRESHOLD = 6000;
84 
85  private static final int DEFAULT_TRACE_FILE_MAX_COUNT = 10;
86  private static final int DEFAULT_TRACE_FILE_MAX_SIZE = 100;
87 
88  private static final String password = "<]mjkQL~B6Uh;^,LWJ+Tdz=(W#WA/8ZGYWg259Ht]`9gG;";
89  private static final List<FileChooser.ExtensionFilter> EXTENSION_FILTERS =
90  new LinkedList<FileChooser.ExtensionFilter>() {{
91  add(new FileChooser.ExtensionFilter("All supported formats", "*." + PTX_EXTENSION, "*." + PPX_EXTENSION));
92  add(new FileChooser.ExtensionFilter("PTX files", "*." + PTX_EXTENSION));
93  add(new FileChooser.ExtensionFilter("PPX files", "*." + PPX_EXTENSION));
94  add(new FileChooser.ExtensionFilter("All files", "*.*"));
95  }};
96 
97  private static final String MAIN_PROCEDURE_NAME = "main";
98 
99  private static final String STYLE_SHEET = "/sample_style.css";
100 
101  private static final String MAIN_FXML = "/SampleForm.fxml";
102  private static final String SAMPLE_TITLE = String.format(
103  "emotive OTX-Runtime API for Java - Reference Application - Version %s",
104  SampleConstants.VERSION
105  );
106  private static final int SAMPLE_WIDTH = 1060;
107  private static final int SAMPLE_HEIGHT = 736;
108  private static final String ICON_PATH = "/Sample.png";
109 
110  private static final int VALUE_STRING_MAX_LENGTH = 1024;
111 
112  //endregion
113 
114  //region Properties
115  private Stage stage;
116 
117  private int cyclic = 1;
118 
119  private IRuntimeManager runtimeManager = null;
120  private IProject project = null;
121  private IPlayerProject playerProject = null;
122  private IProcedure procedureWillExecute = null;
123  private final List<IRuntimeContext> runtimeContexts = new ArrayList<>();
124 
125  private CustomTreeItem startupNode = null;
126 
127  private final String PROCESS_64_BIT = "amd64";
128 
129  private final DefaultCustomScreenImplementation customScreenImplementation = new DefaultCustomScreenImplementation();
130  private final ContextVariableImplementation contextVariableImplementation = new ContextVariableImplementation();
131  private final StateVariableImplementation stateVariableImplementation = new StateVariableImplementation();
132  private final DefaultMeasureImplementation measureImplementation = new DefaultMeasureImplementation();
133  private final DefaultExternalServiceProviderImplementation serviceProviderImplementation = new DefaultExternalServiceProviderImplementation();
134 
135  private final LoggingOutputImpl loggingOutputImpl = new LoggingOutputImpl(this::PrintText);
136  private final BasicScreenOutputImpl basicScreenOutputImpl = new BasicScreenOutputImpl(this::PrintText);
137  private final CustomScreenOutputImpl customScreenOutputImpl = new CustomScreenOutputImpl(this::PrintText);
138  private final ContextVariableOutputImpl contextVariableOutputImpl = new ContextVariableOutputImpl(this::PrintText);
139  private final StateVariableOutputImpl stateVariableOutputImpl = new StateVariableOutputImpl(this::PrintText);
140  private final MeasureOutputImpl measureOutputImpl = new MeasureOutputImpl(this::PrintText);
141  private final I18nOutputImpl i18nOutput = new I18nOutputImpl(this::PrintText);
142  private final SqlOutputImpl sqlOutput = new SqlOutputImpl(this::PrintText);
143  private final ExternalServiceProviderOutputImpl serviceProviderOutputImpl = new ExternalServiceProviderOutputImpl(this::PrintText);
144 
145  private String lastOpenedDirectory = "";
146 
147  HmiWindow hmiWindow = null;
148  KeyDownListener keyDownListener = args -> PrintText(args.ToString());
149 
150  private int lineNumber = 0;
151 
152  private static int defaultPollingTime = 500;
153  private static int defaultBatteryVoltageThreshold = 6000;
154  private boolean useConnectionState = false;
155  private Boolean KL15State = false;
156  private ExpectedState expectedConnectionState = ExpectedState.None;
157  private final Object lock = new Object();
158  private final Object printTextLock = new Object();
159  private final Object eventListenerLock = new Object();
160  private final Object tableParameterLock = new Object();
161 
162  private boolean cyclicExecuteAsyncIsProcessing = false;
163 
164  private SaveSettingUtil userSetting = SaveSettingUtil.Instance();
165  //endregion
166  private Map<IRuntimeContext, Stage> dicMessageDialog;
167 
168  private String runtimePort = DEFAULT_RUNTIME_PORT;
169  private String diagPort = DEFAULT_DIAG_MANAGER_PORT;
170  private String runtimePipeName = DEFAULT_RUNTIME_PIPE_NAME;
171  private String diagPipeName = DEFAULT_DIAG_MANAGER_PIPE_NAME;
172 
173  //region FXML properties
174  @FXML
175  private Button buttonExecuteMain;
176  @FXML
177  private Button btnExecuteProcedureSelected;
178  @FXML
179  private Button buttonCopyRow;
180  @FXML
181  private Button buttonStop;
182  @FXML
183  private Button buttonPause;
184  @FXML
185  private Button buttonContinue;
186  @FXML
187  private Button buttonHMI;
188  @FXML
189  private Button buttonStartStopWebServer;
190  @FXML
191  private Button btnNewInstance;
192  @FXML
193  private TreeView<String> treeViewOtxProject;
194  @FXML
195  private TextField txtPassword;
196  @FXML
197  private TextField textTracePath;
198  @FXML
199  private TextField txtFilePath;
200  @FXML
201  private TextField txtTraceFileMaxCount;
202  @FXML
203  private TextField txtTraceFileMaxSize;
204  @FXML
205  private TextField textRuntimeCommunication;
206  @FXML
207  private TextField textDiagCommunication;
208  @FXML
209  private ListView<String> listViewOutputText;
210  @FXML
211  private Label labelOutputOverflow;
212  @FXML
213  private TableView<CustomTableItem> tableParameter;
214  @FXML
215  private TableColumn<CustomTableItem, String> columnProcedureParamName;
216  @FXML
217  private TableColumn<CustomTableItem, String> columnProcedureParamDataType;
218  @FXML
219  private TableColumn<CustomTableItem, Object> columnProcedureParamValue;
220  @FXML
221  private TableView<CustomTableItem> tableContextVariables;
222  @FXML
223  private TableColumn<CustomTableItem, String> columnContextVariableName;
224  @FXML
225  private TableColumn<CustomTableItem, String> columnContextVariableDataType;
226  @FXML
227  private TableColumn<CustomTableItem, Object> columnContextVariableValue;
228  @FXML
229  private TableView<CustomTableItem> tableStateVariables;
230  @FXML
231  private TableColumn<CustomTableItem, String> columnStateVariableName;
232  @FXML
233  private TableColumn<CustomTableItem, String> columnStateVariableDataType;
234  @FXML
235  private TableColumn<CustomTableItem, Object> columnStateVariableValue;
236  @FXML
237  private TableView<Map.Entry<String, String>> tableProjectSetting;
238  @FXML
239  private TableColumn<Map.Entry<String, String>, String> columnSettingName;
240  @FXML
241  private TableColumn<Map.Entry<String, String>, String> columnSettingValue;
242  @FXML
243  private ComboBox<String> comboBoxCommunicationType;
244  @FXML
245  private Label labelIpcPortPipe;
246  @FXML
247  private ComboBox<String> comboBoxTraceLevel;
248  @FXML
249  private CheckBox checkBoxAsynchron;
250  @FXML
251  private CheckBox checkBoxCyclic;
252  @FXML
253  private CheckBox checkBoxCyclicReload;
254  @FXML
255  private RadioButton radioButtonOutputWindow;
256  @FXML
257  private RadioButton radioButtonDefaultImplementation;
258  @FXML
259  private RadioButton radioButtonNoCustomImplementation;
260  @FXML
261  private Button btnBrowseFile;
262  @FXML
263  private TextField textRuntimeName;
264  @FXML
265  private CheckBox checkBoxUseConnectionState;
266  @FXML
267  private Label labelExpectedState;
268  @FXML
269  private CheckBox checkBoxIgnition;
270  @FXML
271  private Label labelBatteryState;
272  @FXML
273  private Label labelIgnitionState;
274  @FXML
275  private Button buttonCheckBatteryIgnition;
276  @FXML
277  private Label labelPollingTime;
278  @FXML
279  private Label labelVoltageThreshold;
280  @FXML
281  private TextField textBoxPollingTime;
282  @FXML
283  private TextField textBoxBatteryVoltageThreshold;
284  @FXML
285  private Label labelTimeout;
286  @FXML
287  private TextField textBoxTimeout;
288  @FXML
289  private TextField txtProfilingMaxFileSize;
290  @FXML
291  private CheckBox checkBoxProfiling;
292  //endregion
293 
294  java.util.Timer webServerTimer = new java.util.Timer();
295 
296  static {
297  String licenseKey = null;
298  try {
299  licenseKey = (new RijndaelCrypt(password)).DecryptStringAES(SaveSettingUtil.Instance().GetPropertyValue("LicenseKey", ""));
300  } catch (InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException |
301  InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException e) {
302  throw new RuntimeException(e);
303  }
304  if (LicenseUtil.checkLicenseKeyFormat(licenseKey)) {
305  LicenseManager.SetLicenseKey(licenseKey);
306  } else {
307  Alert noLicenseAlert = new Alert(Alert.AlertType.WARNING, "There is an invalid license key format. Please set your new key in license box.");
308  noLicenseAlert.setHeaderText("Invalid license key format");
309  noLicenseAlert.showAndWait();
310  }
311  }
312 
313  public SampleForm() {
314  }
315 
316  public void SetStage(Stage stage) {
317  this.stage = stage;
318 
319  if (this.stage.getTitle() == null) {
320  this.stage.setTitle(GetTitle(false));
321  }
322 
323  this.stage.setOnHidden(event -> {
324  if (webServerTimer != null) {
325  webServerTimer.cancel();
326  }
327  SaveSetting();
328  });
329  InitializeComponent();
330  InitializeRuntimeManagerFirstTime();
331 
332  TimerTask task = new TimerTask() {
333 
334  // run() method to carry out the action of the task
335  public void run() {
336  UpdateWebServerButton();
337  }
338 
339  ;
340  };
341 
342  webServerTimer.schedule(task, 1000, 1000);
343  }
344 
345  private void InitializeComponent() {
346  CustomTreeItem mainRoot = new CustomTreeItem(null);
347  treeViewOtxProject.setRoot(mainRoot);
348  treeViewOtxProject.setShowRoot(false);
349  treeViewOtxProject.getSelectionModel().selectedItemProperty().addListener(this::TreeView_SelectItemListener);
350 
351  columnSettingName.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().getKey()));
352  columnSettingValue.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().getValue()));
353 
354  columnProcedureParamName.setCellValueFactory(new PropertyValueFactory<>("name"));
355  columnProcedureParamDataType.setCellValueFactory(new PropertyValueFactory<>("dataType"));
356  columnProcedureParamValue.setCellValueFactory(new PropertyValueFactory<>("value"));
357 
358  columnContextVariableName.setCellValueFactory(new PropertyValueFactory<>("name"));
359  columnContextVariableDataType.setCellValueFactory(new PropertyValueFactory<>("dataType"));
360  columnContextVariableValue.setCellValueFactory(new PropertyValueFactory<>("value"));
361 
362  columnStateVariableName.setCellValueFactory(new PropertyValueFactory<>("name"));
363  columnStateVariableDataType.setCellValueFactory(new PropertyValueFactory<>("dataType"));
364  columnStateVariableValue.setCellValueFactory(new PropertyValueFactory<>("value"));
365  SetCellFactoryForValueColumn();
366 
367  ObservableList<String> communicationTypes = FXCollections.observableArrayList(SOCKET_COMMUNICATION, PIPE_COMMUNICATION);
368  comboBoxCommunicationType.setItems(communicationTypes);
369  comboBoxCommunicationType.setVisibleRowCount(2);
370 
371  comboBoxCommunicationType.setValue(SOCKET_COMMUNICATION);
372  comboBoxCommunicationType.selectionModelProperty().addListener((observable, oldValue, newValue) -> {
373  comboBoxCommunicateType_Action();
374  });
375  textRuntimeCommunication.setText(DEFAULT_RUNTIME_PORT);
376  textDiagCommunication.setText(DEFAULT_DIAG_MANAGER_PORT);
377 
378  textTracePath.textProperty().addListener((observable, oldValue, newValue) -> UpdateTraceFolder());
379  txtTraceFileMaxCount.textProperty().addListener((observable, oldValue, newValue) -> UpdateTraceFileMaxCount());
380  txtTraceFileMaxSize.textProperty().addListener((observable, oldValue, newValue) -> UpdateTraceFileMaxSize());
381 
382  List<String> traceLevels = new ArrayList<>();
383  for (TraceLevels traceLevel : TraceLevels.values()) {
384  traceLevels.add(traceLevel.name());
385  }
386 
387  comboBoxTraceLevel.setItems(FXCollections.observableArrayList(traceLevels));
388  comboBoxTraceLevel.setVisibleRowCount(7);
389 
390  buttonCopyRow.setDisable(true);
391 
392  listViewOutputText.setItems(FXCollections.observableList(new ArrayList<>()));
393  listViewOutputText.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
394 
395  AddCheckBoxUseConnectionStateListener();
396 
397  this.textBoxPollingTime.setText(String.valueOf(defaultPollingTime));
398  this.textBoxBatteryVoltageThreshold.setText(String.valueOf(defaultBatteryVoltageThreshold));
399 
400  this.checkBoxCyclic.selectedProperty().addListener(observable -> {
401  checkBoxCyclic_Check();
402  });
403 
404  AddListenerForCustomImplRadioButtons();
405  AddProfilingListener();
406  }
407 
408  private void AddProfilingListener()
409  {
410  this.checkBoxProfiling.selectedProperty().addListener(observable -> {
411  checkBoxProfiling_Check();
412  });
413 
414  txtProfilingMaxFileSize.textProperty().addListener((observable, oldValue, newValue) -> txtProfilingMaxFileSize_Action());
415  }
416 
417  private void AddCheckBoxUseConnectionStateListener() {
418  this.checkBoxUseConnectionState.selectedProperty().addListener(observable -> {
419  checkBoxUseConnectionState_Check();
420  });
421 
422  this.checkBoxIgnition.selectedProperty().addListener(observable -> {
423  checkBoxIgnition_Check();
424  });
425 
426  this.checkBoxIgnition.indeterminateProperty().addListener(observable -> {
427  checkBoxIgnition_Check();
428  });
429  }
430 
431  private void AddListenerForCustomImplRadioButtons() {
432  radioButtonDefaultImplementation.selectedProperty().addListener((observable, oldValue, newValue) -> {
433  if (newValue)
434  CheckCustomImplRadioButtonGroup();
435  });
436  radioButtonNoCustomImplementation.selectedProperty().addListener((observable, oldValue, newValue) -> {
437  if (newValue)
438  CheckCustomImplRadioButtonGroup();
439  });
440  radioButtonOutputWindow.selectedProperty().addListener((observable, oldValue, newValue) -> {
441  if (newValue)
442  CheckCustomImplRadioButtonGroup();
443  });
444  }
445 
446  private void InitializeRuntimeManagerFirstTime() {
447  PrintText("Application started");
448  if (runtimeManager != null)
449  return;
450 
451  try {
452  LoadSetting();
453  txtTraceFileMaxCount.setText(Integer.toString(RuntimeConfig.GetInstance().GetTraceFileMaxCount()));
454  txtTraceFileMaxSize.setText(Integer.toString(RuntimeConfig.GetInstance().GetTraceFileMaxSize()));
455  checkBoxProfiling.setSelected(RuntimeConfig.GetInstance().GetProfiling());
456  txtProfilingMaxFileSize.setText(Integer.toString(RuntimeConfig.GetInstance().GetProfilingMaxFileSize()));
457  SetRuntimeManagerEvents();
458  CheckCustomImplRadioButtonGroup();
459  LoadContextFile();
460  PrintText("Initialization finished");
461  } catch (Exception e) {
462  if (runtimeManager == null) {
463  PrintText("Failed to create RuntimeManager.");
464  }
465 
466  }
467 
468  }
469 
470  //region User Settings
471  private void SaveSetting() {
472  HashMap<String, Object> properties = new HashMap<>();
473  properties.put(SampleConstants.PTX_PPX_DIRECTORY, txtFilePath.getText());
474  properties.put(SampleConstants.TRACE_FILE_MAX_COUNT, txtTraceFileMaxCount.getText());
475  properties.put(SampleConstants.TRACE_FILE_MAX_SIZE, txtTraceFileMaxSize.getText());
476  properties.put(SampleConstants.TRACE_LEVEL, RuntimeConfig.GetInstance().GetTraceLevel());
477  properties.put(SampleConstants.TRACE_DIRECTORY, RuntimeConfig.GetInstance().GetTraceFolder());
478  properties.put(SampleConstants.RUNTIME_CONTEXT_NAME, textRuntimeName.getText());
479 
480  properties.put(SampleConstants.ASYNCHRON, checkBoxAsynchron.isSelected());
481  properties.put(SampleConstants.CYCLIC, checkBoxCyclic.isSelected());
482  properties.put(SampleConstants.CYCLIC_RELOAD, checkBoxCyclicReload.isSelected());
483  properties.put(SampleConstants.CUSTOM_IMPL_TYPE, GetCustomImplType());
484 
485  properties.put(SampleConstants.WINDOW_HEIGHT, stage.getScene().getWindow().getHeight());
486  properties.put(SampleConstants.WINDOW_WIDTH, stage.getScene().getWindow().getWidth());
487  properties.put(SampleConstants.WINDOW_LOCATION_X, stage.getScene().getWindow().getX());
488  properties.put(SampleConstants.WINDOW_LOCATION_Y, stage.getScene().getWindow().getY());
489 
490  properties.put(SampleConstants.TIME_OUT, GetTimeout());
491  properties.put(SampleConstants.CONNECTION_STATE, this.useConnectionState);
492  SaveKL15State(properties);
493  properties.put(SampleConstants.POLLING_TIME,
494  this.textBoxPollingTime.getText());
495  properties.put(SampleConstants.VOLTAGE_THRESHOLD,
496  this.textBoxBatteryVoltageThreshold.getText());
497 
498  properties.put(SampleConstants.PROFILING, checkBoxProfiling.isSelected());
499  properties.put(SampleConstants.PROFILING_MAX_FILE_SIZE, txtProfilingMaxFileSize.getText());
500  SaveSocketPortOrPipeName(properties);
501 
502  userSetting.SetPropertyValues(properties);
503  }
504 
505  private void SaveKL15State(HashMap<String, Object> properties) {
506  int kl15IntValue;
507 
508  if (this.KL15State == null) {
509  kl15IntValue = -1;
510  } else if (this.KL15State == true) {
511  kl15IntValue = 1;
512  } else {
513  kl15IntValue = 0;
514  }
515 
516  properties.put(SampleConstants.KL15_STATE, kl15IntValue);
517  }
518 
519  private void SaveSocketPortOrPipeName(HashMap<String, Object> properties) {
520 
521  if (comboBoxCommunicationType.getValue().equals(SOCKET_COMMUNICATION)) {
522 
523  String runtimePort = textRuntimeCommunication.getText().trim();
524  properties.put(SampleConstants.RUNTIME_PORT, runtimePort);
525 
526  String diagPort = textDiagCommunication.getText().trim();
527  properties.put(SampleConstants.DIAG_MANAGER_PORT, diagPort);
528 
529  properties.put(SampleConstants.IPC_TYPE, SOCKET_COMMUNICATION);
530 
531  } else if (comboBoxCommunicationType.getValue().equals(PIPE_COMMUNICATION)) {
532 
533  String runtimePipeName = textRuntimeCommunication.getText().trim();
534  properties.put(SampleConstants.RUNTIME_PIPE_NAME, runtimePipeName);
535 
536  String diagPipeName = textDiagCommunication.getText().trim();
537  properties.put(SampleConstants.DIAG_PIPE_NAME, diagPipeName);
538 
539  properties.put(SampleConstants.IPC_TYPE, PIPE_COMMUNICATION);
540  }
541  }
542 
543  private void LoadSetting() {
544 
545  //Avoid changing the order of this line
546  LoadDefaultPortAndPipeName();
547 
548  LoadPtxPpxDirectoryPath();
549  LoadTraceFileMaxCountAndSize();
550  LoadTraceLevel();
551  LoadTraceFolder();
552  LoadRuntimeContextName();
553 
554  LoadAsyncOption();
555  LoadCyclicOption();
556  LoadCyclicReloadOption();
557  LoadCustomImplType();
558 
559  LoadSampleLocation();
560  LoadSampleSize();
561 
562  LoadTimeOut();
563  LoadConnectionState();
564  LoadKL15State();
565  LoadPollingTime();
566  LoadVoltageThreshold();
567  LoadProfiling();
568  this.EnableConnectionState();
569  SetExpectedState();
570  }
571 
572  private void LoadTraceFileMaxCountAndSize() {
573  String traceFileMaxCount = userSetting.GetPropertyValue(SampleConstants.TRACE_FILE_MAX_COUNT,
574  Integer.toString(DEFAULT_TRACE_FILE_MAX_COUNT));
575  String traceFileMaxSize = userSetting.GetPropertyValue(SampleConstants.TRACE_FILE_MAX_SIZE,
576  Integer.toString(DEFAULT_TRACE_FILE_MAX_SIZE));
577 
578  txtTraceFileMaxCount.setText(traceFileMaxCount);
579  txtTraceFileMaxSize.setText(traceFileMaxSize);
580  }
581 
582  private void LoadDefaultPortAndPipeName() {
583  String runtimePortSavedValue = userSetting.GetPropertyValue(SampleConstants.RUNTIME_PORT, DEFAULT_RUNTIME_PORT);
584  runtimePort = CheckValidPortString(runtimePortSavedValue.trim()) ? runtimePortSavedValue.trim() : DEFAULT_RUNTIME_PORT;
585 
586  String diagPortSavedValue = userSetting.GetPropertyValue(SampleConstants.DIAG_MANAGER_PORT, DEFAULT_DIAG_MANAGER_PORT);
587  diagPort = CheckValidPortString(diagPortSavedValue.trim()) ? diagPortSavedValue.trim() : DEFAULT_DIAG_MANAGER_PORT;
588 
589  String runtimePipeNameSavedValue = userSetting.GetPropertyValue(SampleConstants.RUNTIME_PIPE_NAME, DEFAULT_RUNTIME_PIPE_NAME);
590  runtimePipeName = runtimePipeNameSavedValue.trim().equals("") ? DEFAULT_RUNTIME_PIPE_NAME : runtimePipeNameSavedValue.trim();
591 
592  String diagPipeNameSavedValue = userSetting.GetPropertyValue(SampleConstants.DIAG_PIPE_NAME, DEFAULT_DIAG_MANAGER_PIPE_NAME);
593  diagPipeName = diagPipeNameSavedValue.trim().equals("") ? DEFAULT_DIAG_MANAGER_PIPE_NAME : diagPipeNameSavedValue.trim();
594 
595  //Init RuntimeManager for the first time
596  String icpType = userSetting.GetPropertyValue(SampleConstants.IPC_TYPE, SOCKET_COMMUNICATION);
597 
598  if (icpType.equals(SOCKET_COMMUNICATION)) {
599  textRuntimeCommunication.setText(runtimePort);
600  textDiagCommunication.setText(diagPort);
601  comboBoxCommunicationType.setValue(SOCKET_COMMUNICATION);
602  } else {
603  textRuntimeCommunication.setText(runtimePipeName);
604  textDiagCommunication.setText(diagPipeName);
605  comboBoxCommunicationType.setValue(PIPE_COMMUNICATION);
606  }
607 
608  InitializeRuntimeManagerByIpcTypeTextBox();
609  }
610 
611  private void LoadPtxPpxDirectoryPath() {
612  txtFilePath.setText(userSetting.GetPropertyValue(SampleConstants.PTX_PPX_DIRECTORY, ""));
613  }
614 
615  private void LoadTraceLevel() {
616 
617  String traceLevelStringValue = userSetting.GetPropertyValue(
618  SampleConstants.TRACE_LEVEL,
619  RuntimeConfig.GetInstance().GetTraceLevel().toString()
620  ).trim();
621 
622  comboBoxTraceLevel.setValue(traceLevelStringValue);
623  UpdateTraceLevel();
624  }
625 
626  private void LoadTraceFolder() {
627 
628  String traceDirectory = userSetting.GetPropertyValue(
629  SampleConstants.TRACE_DIRECTORY,
630  RuntimeConfig.GetInstance().GetTraceFolder()
631  ).trim();
632 
633  textTracePath.setText(traceDirectory);
634  UpdateTraceFolder();
635  }
636 
637  private void LoadRuntimeContextName() {
638  textRuntimeName.setText(userSetting.GetPropertyValue(SampleConstants.RUNTIME_CONTEXT_NAME, ""));
639  }
640 
641  private void LoadAsyncOption() {
642 
643  boolean asynchronValue = Boolean.parseBoolean(userSetting.GetPropertyValue(
644  SampleConstants.ASYNCHRON, "true"));
645  checkBoxAsynchron.setSelected(asynchronValue);
646  }
647 
648  private void LoadCyclicOption() {
649  boolean cyclicValue = Boolean.parseBoolean(userSetting.GetPropertyValue(
650  SampleConstants.CYCLIC, "true"));
651 
652  checkBoxCyclic.setSelected(cyclicValue);
653  }
654 
655  private void LoadCyclicReloadOption() {
656 
657  if (checkBoxCyclicReload.isDisable())
658  return;
659 
660  boolean cyclicReloadValue = Boolean.parseBoolean(userSetting.GetPropertyValue(
661  SampleConstants.CYCLIC_RELOAD, "true"));
662 
663  checkBoxCyclicReload.setSelected(cyclicReloadValue);
664  }
665 
666 
667  private void LoadCustomImplType() {
668  SampleConstants.CustomImplType customImplType = SampleConstants.CustomImplType.valueOf(
669  userSetting.GetPropertyValue(
670  SampleConstants.CUSTOM_IMPL_TYPE,
671  SampleConstants.CustomImplType.DefaultCustomImpl.toString()).trim());
672 
673  LoadCustomImplType(customImplType);
674  }
675 
676  private void LoadCustomImplType(SampleConstants.CustomImplType customImplType) {
677 
678  switch (customImplType) {
679  case OutputImpl:
680  radioButtonOutputWindow.setSelected(true);
681  break;
682  case NoCustom:
683  radioButtonNoCustomImplementation.setSelected(true);
684  break;
685  default:
686  radioButtonDefaultImplementation.setSelected(true);
687  break;
688  }
689  }
690 
691  private void LoadSampleSize() {
692  if (stage == null)
693  return;
694 
695  double sampleHeight = Double.parseDouble(
696  userSetting.GetPropertyValue(
697  SampleConstants.WINDOW_HEIGHT,
698  Integer.toString(SAMPLE_HEIGHT)
699  ).trim());
700 
701  double sampleWidth = Double.parseDouble(
702  userSetting.GetPropertyValue(
703  SampleConstants.WINDOW_WIDTH,
704  Integer.toString(SAMPLE_WIDTH)
705  ).trim());
706 
707  stage.setHeight(sampleHeight);
708  stage.setWidth(sampleWidth);
709 
710  }
711 
712  private void LoadSampleLocation() {
713 
714  if (stage == null)
715  return;
716 
717  double coordinateX = Double.parseDouble(
718  userSetting.GetPropertyValue(
719  SampleConstants.WINDOW_LOCATION_X, "0"
720  ).trim());
721 
722  double coordinateY = Double.parseDouble(
723  userSetting.GetPropertyValue(
724  SampleConstants.WINDOW_LOCATION_Y, "0"
725  ).trim());
726 
727  Point location = new Point((int) coordinateX, (int) coordinateY);
728  if (CheckFormIsInBound(location)) {
729  stage.setX(coordinateX);
730  stage.setY(coordinateY);
731  return;
732  }
733 
734  stage.centerOnScreen();
735  }
736 
737  private boolean CheckFormIsInBound(Point point) {
738  GraphicsDevice[] screenDevices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
739 
740  for (GraphicsDevice screen : screenDevices) {
741  if (screen.getDefaultConfiguration().getBounds().contains(point))
742  return true;
743  }
744 
745  return false;
746  }
747 
748  private void LoadTimeOut() {
749  textBoxTimeout.setText(userSetting.GetPropertyValue(
750  SampleConstants.TIME_OUT, "0"
751  ).trim());
752  }
753 
754  private void LoadConnectionState() {
755  this.useConnectionState = Boolean.parseBoolean(userSetting.GetPropertyValue(
756  SampleConstants.CONNECTION_STATE, "false"
757  ).trim());
758 
759  this.checkBoxUseConnectionState.setSelected(this.useConnectionState);
760  }
761 
762  private void LoadKL15State() {
763  if (checkBoxIgnition.isDisable() == true)
764  return;
765 
766  int kl15StateIntValue;
767  try {
768  kl15StateIntValue = Integer.parseInt(userSetting.GetPropertyValue(
769  SampleConstants.KL15_STATE,
770  "0").trim());
771  } catch (Exception ex) {
772  kl15StateIntValue = 0;
773  }
774 
775  if (kl15StateIntValue != -1) {
776  this.KL15State = kl15StateIntValue == 1;
777  this.checkBoxIgnition.setSelected(KL15State);
778  } else {
779  //case where checkBoxKL15 is indeterminate
780  this.KL15State = null;
781  this.checkBoxIgnition.setIndeterminate(true);
782  return;
783  }
784 
785  }
786 
787  private void LoadPollingTime() {
788 
789  int pollingTime;
790  try {
791  pollingTime = Integer.parseInt(userSetting.GetPropertyValue(
792  SampleConstants.POLLING_TIME, Integer.toString(DEFAULT_POLLING_TIME)
793  ).trim());
794  } catch (Exception ex) {
795  pollingTime = DEFAULT_POLLING_TIME;
796  }
797 
798  this.textBoxPollingTime.setText(Integer.toString(pollingTime));
799  }
800 
801  private void LoadVoltageThreshold() {
802 
803  int batteryVoltageThreshold;
804  try {
805  batteryVoltageThreshold = Integer.parseInt(userSetting.GetPropertyValue(
806  SampleConstants.VOLTAGE_THRESHOLD, Integer.toString(DEFAULT_BATTERY_VOLTAGE_THRESHOLD)
807  ).trim());
808  } catch (Exception ex) {
809  batteryVoltageThreshold = DEFAULT_BATTERY_VOLTAGE_THRESHOLD;
810  }
811 
812 
813  this.textBoxBatteryVoltageThreshold.setText(Integer.toString(batteryVoltageThreshold));
814  }
815 
816  private void LoadProfiling()
817  {
818  checkBoxProfiling.setSelected(Boolean.parseBoolean(userSetting.GetPropertyValue(
819  SampleConstants.PROFILING, "false")));
820  txtProfilingMaxFileSize.setText(userSetting.GetPropertyValue(
821  SampleConstants.PROFILING_MAX_FILE_SIZE, "50"));
822  }
823  //endregion
824 
825  //Help "Value" cell display checkbox when value is Boolean
826  private void SetCellFactoryForValueColumn() {
827 
828  this.columnProcedureParamValue.setCellFactory(column -> new CustomTableCell(this::PrintText));
829 
830  this.columnContextVariableValue.setCellFactory(column -> new CustomTableCell(this::PrintText));
831 
832  this.columnStateVariableValue.setCellFactory(column -> new CustomTableCell(this::PrintText));
833 
834  this.columnSettingValue.setCellFactory(TextFieldTableCell.forTableColumn());
835  this.columnSettingValue.setOnEditCommit(e -> e.getTableView()
836  .getItems()
837  .get(
838  e.getTablePosition()
839  .getRow()
840  )
841  .setValue(
842  e.getNewValue()
843  )
844  );
845  }
846 
847  @FXML
848  private void btnNewInstance_Action() {
849  try {
850  OpenNewSampleForm(true);
851  } catch (Exception e) {
852  PrintText("Exception" + e.getMessage());
853  }
854  }
855 
856  @FXML
857  private void btnNewInstanceNewThreadAction() {
858  Thread newSampleThread = new Thread(() -> {
859  try {
860  OpenNewSampleForm(false);
861  } catch (IOException e) {
862  PrintText("Exception: " + e.getMessage());
863  }
864  });
865  newSampleThread.setName("New Sample Instance");
866  newSampleThread.setDaemon(true);
867  newSampleThread.start();
868  }
869 
870  private synchronized void OpenNewSampleForm(boolean isChild) throws IOException {
871  FXMLLoader loader = new FXMLLoader(getClass().getResource(MAIN_FXML));
872 
873  Scene scene = new Scene(loader.load(), SAMPLE_WIDTH, SAMPLE_HEIGHT);
874  scene.getStylesheets().add(STYLE_SHEET);
875 
876  long threadID = Thread.currentThread().getId();
877 
878  Platform.runLater(() -> {
879  Stage stage = new Stage();
880  stage.getIcons().add(new Image(this.getClass().getResourceAsStream(ICON_PATH)));
881  stage.setScene(scene);
882 
883  String title = GetTitle(isChild);
884  stage.setTitle(title);
885 
886  SampleForm controller = loader.getController();
887  controller.SetStage(stage);
888 
889  stage.show();
890  });
891  }
892 
893  private String GetTitle(boolean isChild) {
894  return String.format(
895  "emotive OTX-Runtime API for Java - Reference Application - Version %s - %s Bit - %s - Thread-ID %o%s",
896  SampleConstants.VERSION,
897  Is64Bit() ? "64" : "32",
898  isChild ? "Child Instance" : "Main Instance",
899  Thread.currentThread().getId(),
900  IsAdmin() ? " - Administrator" : ""
901  );
902  }
903 
904  private boolean Is64Bit() {
905  try {
906  String osArchitecture = System.getProperty("os.arch");
907  return osArchitecture.equals(PROCESS_64_BIT);
908  } catch (Exception ex) {
909  return false;
910  }
911  }
912 
913  private boolean IsAdmin() {
914  try {
915  String command = "reg query \"HKU\\S-1-5-19\"";
916  Process p = Runtime.getRuntime().exec(command);
917  p.waitFor(); // Wait for for command to finish
918  int exitValue = p.exitValue(); // If exit value 0, then admin user.
919 
920  return 0 == exitValue;
921 
922  } catch (Exception e) {
923  e.printStackTrace();
924  }
925 
926  return false;
927  }
928 
929  @FXML
930  void portTextField_KeyReleased() {
931  if (comboBoxCommunicationType.getValue().trim().equals(PIPE_COMMUNICATION)) {
932  textRuntimeCommunication.setStyle(null);
933  textDiagCommunication.setStyle(null);
934 
935  CreateRuntimeManagerAndSetConfig();
936  return;
937  }
938 
939  boolean isValidRuntimePort = CheckValidPortString(textRuntimeCommunication.getText());
940  boolean isValidDiagPort = CheckValidPortString(textDiagCommunication.getText());
941 
942  if (!isValidRuntimePort) {
943  textRuntimeCommunication.setStyle("-fx-text-box-border: #B22222; -fx-focus-color: #B22222;");
944  } else {
945  textRuntimeCommunication.setStyle(null);
946  }
947 
948  if (!isValidDiagPort) {
949  textDiagCommunication.setStyle("-fx-text-box-border: #B22222; -fx-focus-color: #B22222;");
950  } else {
951  textDiagCommunication.setStyle(null);
952  }
953 
954  if (isValidRuntimePort && isValidDiagPort)
955  CreateRuntimeManagerAndSetConfig();
956  }
957 
958  private boolean CheckValidPortString(String port) {
959 
960  if (port.trim().isEmpty())
961  return false;
962 
963  try {
964  Integer.parseInt(port);
965  return true;
966  } catch (NumberFormatException nfe) {
967  return false;
968  }
969  }
970 
971  @FXML
972  private void checkBoxCyclic_Check() {
973  checkBoxCyclicReload.setDisable(!checkBoxCyclic.isSelected());
974  checkBoxCyclicReload.setSelected(false);
975  }
976 
977  private void SetExpectedState() {
978  if (this.useConnectionState) {
979  if (this.KL15State == null) {
980  this.expectedConnectionState = ExpectedState.BatteryOn;
981  } else if (this.KL15State) {
982  this.expectedConnectionState = ExpectedState.IgnitionOn;
983  } else {
984  this.expectedConnectionState = ExpectedState.IgnitionOff;
985  }
986  } else {
987  this.expectedConnectionState = ExpectedState.None;
988  }
989  }
990 
991  @FXML
992  private void checkBoxUseConnectionState_Check() {
993  this.useConnectionState = this.checkBoxUseConnectionState.isSelected();
994  this.EnableConnectionState();
995  this.SetExpectedState();
996  }
997 
998  @FXML
999  private void checkBoxProfiling_Check() {
1000  RuntimeConfig.GetInstance().SetProfiling(checkBoxProfiling.isSelected());
1001  }
1002 
1003  @FXML
1004  private void txtProfilingMaxFileSize_Action() {
1005  try {
1006  RuntimeConfig.GetInstance().SetProfilingMaxFileSize(Integer.parseInt(txtProfilingMaxFileSize.getText()));
1007  } catch (java.lang.Exception ex) {
1008  PrintText("Exception: " + ex.getMessage());
1009  }
1010 
1011  PrintText("ProfilingMaxFileSize is " + Integer.toString(RuntimeConfig.GetInstance().GetProfilingMaxFileSize()));
1012  }
1013 
1014  private void EnableConnectionState() {
1015  this.labelExpectedState.setDisable(!this.useConnectionState);
1016  this.labelBatteryState.setDisable(!this.useConnectionState);
1017  this.checkBoxIgnition.setDisable(!this.useConnectionState);
1018  this.labelPollingTime.setDisable(!this.useConnectionState);
1019  this.textBoxPollingTime.setDisable(!this.useConnectionState);
1020  this.labelVoltageThreshold.setDisable(!this.useConnectionState);
1021  this.textBoxBatteryVoltageThreshold.setDisable(!this.useConnectionState);
1022  this.buttonCheckBatteryIgnition.setDisable(!this.useConnectionState);
1023  }
1024 
1025  @FXML
1026  private void checkBoxIgnition_Check() {
1027  if (checkBoxIgnition.isIndeterminate()) {
1028  this.KL15State = null;
1029  } else if (!this.checkBoxIgnition.isSelected()) {
1030  this.KL15State = false;
1031  } else {
1032  this.KL15State = true;
1033  }
1034 
1035  this.SetExpectedState();
1036  }
1037 
1038  private void SetIconStateChanged(Label button, String imagePath) {
1039  URL imageUrl = getClass().getResource(imagePath);
1040  Image image = null;
1041  try {
1042  image = new Image(imageUrl.openStream());
1043  Node node = button.getGraphic();
1044  ImageView imageView = (ImageView) node;
1045  imageView.setImage(image);
1046  } catch (Exception e) {
1047  e.printStackTrace();
1048  }
1049  }
1050 
1051  private void CheckBatteryIgnitionState(IRuntimeManager runtimeManager) {
1052  if (this.useConnectionState) {
1053  runtimeManager.GetDiagConnectionState().SetPollingTime(Integer.parseInt(this.textBoxPollingTime.getText()));
1054  runtimeManager.GetDiagConnectionState().SetBatteryVoltageThreshold(Integer.parseInt(this.textBoxBatteryVoltageThreshold.getText()));
1055 
1056  ClampState batteryState = runtimeManager.GetDiagConnectionState().GetBatteryState();
1057  ClampState ignitionState = runtimeManager.GetDiagConnectionState().GetIgnitionState();
1058 
1059  SetBatteryIgnitionState(batteryState, ignitionState);
1060 
1061  PrintText("Check DiagConnection State - BatteryState = " + batteryState.toString() + ", IgnitionState = " + ignitionState.toString());
1062  }
1063  }
1064 
1065  private void SetBatteryIgnitionState(ClampState batteryState, ClampState ignitionState) {
1066  switch (batteryState) {
1067  case NotAvailable:
1068  this.SetIconStateChanged(this.labelBatteryState, "/IconBatteryNotAvailable16.png");
1069  break;
1070  case Off:
1071  this.SetIconStateChanged(this.labelBatteryState, "/IconBatteryOff16.png");
1072  break;
1073  case On:
1074  this.SetIconStateChanged(this.labelBatteryState, "/IconBatteryOn16.png");
1075  break;
1076  }
1077 
1078  switch (ignitionState) {
1079  case NotAvailable:
1080  this.SetIconStateChanged(this.labelIgnitionState, "/IconIgnitionNotAvailable16.png");
1081  break;
1082  case Off:
1083  this.SetIconStateChanged(this.labelIgnitionState, "/IconIgnitionOff16.png");
1084  break;
1085  case On:
1086  this.SetIconStateChanged(this.labelIgnitionState, "/IconIgnitionOn16.png");
1087  break;
1088  }
1089  }
1090 
1091  private void ShowConnectionStateMessage(IRuntimeContext runtimeContext) {
1092  if (runtimeContext != null) {
1093  switch (this.expectedConnectionState) {
1094  case BatteryOn:
1095  this.PrintText("----------------------------------------------------------------------------------------------------------------------------------------------");
1096  this.PrintText("-- Not expected connection state: Either it is not possible to communicate with the VCI or the battery is not connected. Please connect it! --");
1097  this.PrintText("----------------------------------------------------------------------------------------------------------------------------------------------");
1098  break;
1099  case IgnitionOff:
1100  this.PrintText("------------------------------------------------------------------------------------");
1101  this.PrintText("-- Not expected connection state: The ignition must be OFF. Please switch it OFF! --");
1102  this.PrintText("------------------------------------------------------------------------------------");
1103  break;
1104  case IgnitionOn:
1105  this.PrintText("----------------------------------------------------------------------------------");
1106  this.PrintText("-- Not expected connection state: The ignition must be ON. Please switch it ON! --");
1107  this.PrintText("----------------------------------------------------------------------------------");
1108  break;
1109  default:
1110  break;
1111  }
1112  }
1113  }
1114 
1115  @FXML
1116  void textBoxPollingTime_Action() {
1117  try {
1118  Integer.parseInt(this.textBoxPollingTime.getText());
1119  } catch (NumberFormatException nfe) {
1120  this.textBoxPollingTime.setText(String.valueOf(defaultPollingTime));
1121  }
1122  }
1123 
1124  @FXML
1125  void textBoxBatteryVoltageThreshold_Action() {
1126  try {
1127  Integer.parseInt(this.textBoxBatteryVoltageThreshold.getText());
1128  } catch (NumberFormatException nfe) {
1129  this.textBoxBatteryVoltageThreshold.setText(String.valueOf(defaultBatteryVoltageThreshold));
1130  }
1131  }
1132 
1133  @FXML
1134  private void buttonClearOutput_Click(MouseEvent event) {
1135  this.listViewOutputText.setItems(FXCollections.observableList(new ArrayList<>()));
1136  buttonCopyRow.setDisable(true);
1137  labelOutputOverflow.setVisible(false);
1138  lineNumber = 0;
1139  }
1140 
1141  @FXML
1142  private void buttonCopyRow_Click(MouseEvent event) {
1143  String copyText = "";
1144  copyText = this.listViewOutputText.getSelectionModel().getSelectedItem();
1145 
1146  if (copyText.isEmpty()) {
1147  return;
1148  }
1149 
1150  final Clipboard clipboard = Clipboard.getSystemClipboard();
1151  final ClipboardContent content = new ClipboardContent();
1152  content.putString(copyText);
1153  clipboard.setContent(content);
1154  }
1155 
1156  @FXML
1157  private void comboBoxCommunicateType_Action() {
1158  final String communicationType = comboBoxCommunicationType.getValue().trim();
1159 
1160  switch (communicationType) {
1161  case SOCKET_COMMUNICATION:
1162  labelIpcPortPipe.setText(SampleConstants.LABEL_IPC_PORT_TEXT);
1163 
1164  textRuntimeCommunication.setText(runtimePort);
1165  textDiagCommunication.setText(diagPort);
1166  break;
1167  case PIPE_COMMUNICATION:
1168  labelIpcPortPipe.setText(SampleConstants.LABEL_IPC_PIPE_TEXT);
1169 
1170  textRuntimeCommunication.setText(runtimePipeName);
1171  textDiagCommunication.setText(diagPipeName);
1172  break;
1173  }
1174 
1175  CreateRuntimeManagerAndSetConfig();
1176  }
1177 
1178  @FXML
1179  private void btnBrowseFile_Click(ActionEvent event) {
1180 
1181  File file = OpenBrowseFileWindow();
1182 
1183  if (file != null) {
1184  String filePath = file.toPath().toAbsolutePath().normalize().toString();
1185  txtFilePath.clear();
1186  txtFilePath.appendText(filePath);
1187  textRuntimeName.clear();
1188  LoadContextFile();
1189  }
1190  }
1191 
1192  private File OpenBrowseFileWindow() {
1193  FileChooser fileChooser = new FileChooser();
1194  fileChooser.getExtensionFilters().addAll(EXTENSION_FILTERS);
1195 
1196  if (lastOpenedDirectory != null && !lastOpenedDirectory.trim().isEmpty())
1197  fileChooser.setInitialDirectory(new File(lastOpenedDirectory));
1198 
1199  File file = fileChooser.showOpenDialog(stage);
1200  return file;
1201  }
1202 
1203  @FXML
1204  private void btnBrowseTraceFolder_Action(ActionEvent event) {
1205 
1206  File directory = OpenBrowseDirectoryWindow();
1207 
1208  if (directory != null) {
1209  String directoryPath = directory.toPath().toAbsolutePath().normalize().toString();
1210  textTracePath.clear();
1211  textTracePath.appendText(directoryPath);
1212 
1213  }
1214  }
1215 
1216  private File OpenBrowseDirectoryWindow() {
1217  DirectoryChooser directoryChooser = new DirectoryChooser();
1218 
1219  Path existedDirectoryPath = Paths.get(textTracePath.getText());
1220 
1221  if (Files.exists(existedDirectoryPath))
1222  directoryChooser.setInitialDirectory(new File(existedDirectoryPath.toString()));
1223 
1224  return directoryChooser.showDialog(stage);
1225  }
1226 
1227  @FXML
1228  private void btnReload_Action(ActionEvent event) {
1229  LoadContextFile();
1230  textRuntimeName.clear();
1231  }
1232 
1233  @FXML
1234  private void btnOpenFile_Action(ActionEvent event) {
1235  String tracePath = textTracePath.getText();
1236  if (hostServices != null
1237  && !tracePath.isEmpty())
1238  hostServices.showDocument(Paths.get(tracePath).toAbsolutePath().toString());
1239  }
1240 
1241  private void TreeView_SelectItemListener(
1242  ObservableValue observable,
1243  Object oldValue,
1244  Object newValue
1245  ) {
1246  tableParameter.getItems().clear();
1247  tableContextVariables.getItems().clear();
1248  tableStateVariables.getItems().clear();
1249 
1250  if (newValue == null)
1251  return;
1252 
1253  CustomTreeItem node = (CustomTreeItem) newValue;
1254 
1255  if (node.getItem() instanceof IProcedure) {
1256  ResetContextVariableCaches();
1257  IProcedure procedure = (IProcedure) node.getItem();
1258  UpdateTable(procedure);
1259  this.btnExecuteProcedureSelected.setDisable(false);
1260  }
1261  }
1262 
1263  private void ResetContextVariableCaches() {
1264  contextVariableImplementation.ClearCaches();
1265 
1266  contextVariableOutputImpl.ClearCaches();
1267  }
1268 
1269  @FXML
1270  private void contextVariableColumnValue_OnCommit(TableColumn.CellEditEvent event) {
1271  Object value = event.getNewValue();
1272  CustomTableItem contextTableItem = tableContextVariables.getItems().get(event.getTablePosition().getRow());
1273 
1274  try {
1275  contextTableItem.setValue(value);
1276  //we will save value with fullName of context, if not the bug of #10798 occurs.
1277  //Because the name of context variable in imported document may have the same name.
1278  String fullNameContextVariable = ((IContextVariable) contextTableItem.getModel()).GetDocument().GetFullName() +
1279  '.' + ((IContextVariable) contextTableItem.getModel()).GetName();
1280  this.contextVariableImplementation.SetContextVariableValue(fullNameContextVariable, value);
1281  this.contextVariableOutputImpl.SetContextVariable(fullNameContextVariable, value);
1282 
1283  } catch (Exception e) {
1284  PrintText("Exception: " + e.getMessage());
1285  }
1286  }
1287 
1288  @FXML
1289  private void buttonReadSetting_Click(MouseEvent event) {
1290  if (this.playerProject != null)
1291  ReadSettings(this.playerProject.GetSettings());
1292  else if (this.project != null) {
1293  ReadSettings(this.project.GetSettings());
1294  }
1295  }
1296 
1297  private void ReadSettings(Map<String, String> settings) {
1298 
1299  tableProjectSetting.getItems().clear();
1300 
1301  ObservableList<Map.Entry<String, String>> items = FXCollections.observableArrayList(settings.entrySet());
1302  tableProjectSetting.setItems(items);
1303 
1304  PrintText("Finish Reading Settings");
1305  }
1306 
1307  @FXML
1308  private void buttonWriteSetting_Click(MouseEvent event) {
1309  WriteSettings();
1310  }
1311 
1312  private void WriteSettings() {
1313  if (project == null && playerProject == null)
1314  return;
1315 
1316  int selectedSettingPosition = 0;
1317 
1318  if (tableProjectSetting.getSelectionModel().getSelectedItems() != null)
1319  selectedSettingPosition = tableProjectSetting.getSelectionModel().getFocusedIndex();
1320 
1321  try {
1322  Map<String, String> newSetting = tableProjectSetting.getItems().stream()
1323  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
1324 
1325  if (playerProject != null) {
1326  playerProject.SetSettings(newSetting);
1327  ReadSettings(playerProject.GetSettings()); // refresh table
1328  } else {
1329  project.SetSettings(newSetting);
1330  ReadSettings(project.GetSettings()); // refresh table
1331  }
1332  tableProjectSetting.getSelectionModel().select(selectedSettingPosition); //focus on previous selected row
1333 
1334  PrintText("Finish Writing Setting!");
1335  } catch (Exception ex) {
1336  PrintText("Exception when Writing settings: " + ex.getMessage());
1337  }
1338  }
1339 
1340  @FXML
1341  private void buttonStop_Click(MouseEvent event) {
1342  checkBoxCyclic.setSelected(false);
1343  checkBoxCyclic_Check();
1344  if (runtimeManager != null) {
1345  runtimeManager.StopAll();
1346  }
1347  }
1348 
1349  @FXML
1350  private void buttonHmi_Click(MouseEvent event) {
1351  buttonHMI.setDisable(true);
1352  hmiWindow = new HmiWindow();
1353  hmiWindow.addWindowListener(new HmiWindowListener());
1354 
1355  hmiWindow.addComponentListener(new HmiComponentAdapter());
1356 
1357  hmiWindow.pack();
1358  hmiWindow.setVisible(true);
1359  hmiWindow.setBounds(100, 100, 700, 500);
1360  if (customScreenImplementation != null) {
1361  customScreenImplementation.SetHmiScreenHandle(hmiWindow.GetHandle());
1362  }
1363  }
1364 
1365  private void SetIconStateChanged(Button button, String imagePath) {
1366  URL imageUrl = getClass().getResource(imagePath);
1367  Image image = null;
1368  try {
1369  image = new Image(imageUrl.openStream());
1370  Node node = button.getGraphic();
1371  ImageView imageView = (ImageView) node;
1372  imageView.setImage(image);
1373  } catch (Exception e) {
1374  e.printStackTrace();
1375  }
1376  }
1377 
1378  int isStartWebSever = -1;
1379 
1380  private void UpdateWebServerButton() {
1381  if (customScreenImplementation == null) {
1382  this.buttonStartStopWebServer.setDisable(true);
1383  return;
1384  }
1385 
1386  this.buttonStartStopWebServer.setDisable(false);
1387  if (DefaultCustomScreenImplementation.IsStartedHtmlWebserver()) // Has Start WebServer
1388  {
1389  if (isStartWebSever == 1) {
1390  return;
1391  }
1392 
1393  this.SetIconStateChanged(this.buttonStartStopWebServer, "/StopWebServer.png");
1394  Platform.runLater(() -> {
1395  this.buttonStartStopWebServer.setText("Stop WebServer");
1396  });
1397  isStartWebSever = 1;
1398  } else {
1399  if (isStartWebSever == 0) {
1400  return;
1401  }
1402 
1403  this.SetIconStateChanged(this.buttonStartStopWebServer, "/StartWebServer.png");
1404  Platform.runLater(() -> {
1405  this.buttonStartStopWebServer.setText("Start WebServer");
1406  });
1407  isStartWebSever = 0;
1408  }
1409  }
1410 
1411  @FXML
1412  private void buttonStartStopWebServer_Click(MouseEvent event) {
1413  if (customScreenImplementation == null) {
1414  return;
1415  }
1416 
1417  if (!DefaultCustomScreenImplementation.IsStartedHtmlWebserver()) {
1418  customScreenImplementation.StartHtmlWebServer();
1419  } else {
1420  customScreenImplementation.StopHtmlWebServer();
1421  }
1422  }
1423 
1424  @FXML
1425  private void comboBoxTraceLevel_Action(ActionEvent actionEvent) {
1426  UpdateTraceLevel();
1427  }
1428 
1429  private class HmiWindowListener implements WindowListener {
1430  @Override
1431  public void windowOpened(WindowEvent e) {
1432 
1433  }
1434 
1435  @Override
1436  public void windowClosing(WindowEvent e) {
1437  if (customScreenImplementation != null) {
1438  customScreenImplementation.SetHmiScreenHandle(0);
1439  customScreenImplementation.CloseAllChildScreens(hmiWindow.GetHandle());
1440  }
1441  buttonHMI.setDisable(false);
1442  }
1443 
1444  @Override
1445  public void windowClosed(WindowEvent e) {
1446 
1447  }
1448 
1449  @Override
1450  public void windowIconified(WindowEvent e) {
1451 
1452  }
1453 
1454  @Override
1455  public void windowDeiconified(WindowEvent e) {
1456 
1457  }
1458 
1459  @Override
1460  public void windowActivated(WindowEvent e) {
1461 
1462  }
1463 
1464  @Override
1465  public void windowDeactivated(WindowEvent e) {
1466 
1467  }
1468  }
1469 
1470  private class HmiComponentAdapter extends ComponentAdapter {
1471  @Override
1472  public void componentResized(ComponentEvent e) {
1473  super.componentResized(e);
1474  customScreenImplementation.RefreshHmiScreen();
1475  }
1476  }
1477 
1478  @FXML
1479  private void buttonExecuteMain_Click(MouseEvent event) {
1480  try {
1481  if (this.project != null) {
1482  this.procedureWillExecute = project.GetMainProcedure();
1483  this.ExecuteProcedure();
1484  }
1485  else {
1486  PrintText("There is no project has been loaded. Please reload the project");
1487  }
1488 
1489  } catch (Exception ex) {
1490  PrintText("Exception: " + ex.getMessage());
1491  }
1492  }
1493 
1494  @FXML
1495  private void btnExecuteProcedureSelected_Click(MouseEvent event) {
1496  try {
1497  CustomTreeItem node = (CustomTreeItem) treeViewOtxProject.getSelectionModel().getSelectedItem();
1498 
1499  if (node == null ||
1500  !(node.getItem() instanceof IProcedure)) {
1501  PrintText("Please select a procedure");
1502  } else {
1503  this.procedureWillExecute = (IProcedure) node.getItem();
1504  ExecuteProcedure();
1505  }
1506  } catch (Exception ex) {
1507  PrintText("Exception: " + ex.getMessage());
1508  }
1509 
1510  }
1511 
1512  // TODO: check again if RuntimeManger should be re-initialize before run??
1513  private void CreateRuntimeManagerAndSetConfig() {
1514 
1515  InitializeRuntimeManagerByIpcTypeTextBox();
1516 
1517  if (this.runtimeManager != null) {
1518  UpdateTraceLevel();
1519  UpdateTraceFolder();
1520  UpdateTraceFileMaxCount();
1521  UpdateTraceFileMaxSize();
1522  SetRuntimeManagerEvents();
1523  CheckCustomImplRadioButtonGroup();
1524  }
1525  }
1526 
1527  private void SetRuntimeManagerEvents() {
1528  runtimeManager.AddProcedureStartedListener(this::ProcedureStarted);
1529  runtimeManager.AddProcedureFinishedListener(this::ProcedureFinished);
1530  runtimeManager.AddProcedureAbortedListener(this::ProcedureAborted);
1531  runtimeManager.AddProcedureStoppedListener(this::ProcedureStopped);
1532  runtimeManager.AddProcedurePausedListener(this::ProcedurePaused);
1533  runtimeManager.AddProcedurePendingListener(this::ProcedurePending);
1534  runtimeManager.AddDiagConnectionStateChangedListener(this::DiagConnectionStateChanged);
1535  runtimeManager.AddProcedureContinuedListener(this::ProcedureContinued);
1536  runtimeManager.AddProcedureTimeoutListener(this::ProcedureTimeout);
1537  runtimeManager.AddInOutParameterValueChangedListener(this::InOutParameterValueChanged);
1538 
1539  PrintText("Initialization of runtime events finished");
1540  }
1541 
1542  private void InitializeRuntimeManagerByIpcTypeTextBox() {
1543  String ipcType = comboBoxCommunicationType.getValue().trim();
1544  String statusInitializeRuntimeManager;
1545 
1546  try {
1547  if (ipcType.equals(SOCKET_COMMUNICATION)) {
1548 
1549  int rtPort = Integer.parseInt(textRuntimeCommunication.getText());
1550  if (textDiagCommunication.getText().trim().isEmpty()) {
1551  this.runtimeManager = RuntimeManagerFactory.CreateSocketRuntimeManager(rtPort);
1552  } else {
1553  int diagPort = Integer.parseInt(textDiagCommunication.getText());
1554  this.runtimeManager = RuntimeManagerFactory.CreateSocketRuntimeManager(rtPort, diagPort);
1555  }
1556 
1557  PrintText("Socket Runtime Manager (MinBinVersion: " + RuntimeConfig.GetInstance().GetMinBinVersion() + ") created");
1558 
1559  } else if (ipcType.equals(PIPE_COMMUNICATION)) {
1560  String rtPipeName = textRuntimeCommunication.getText().trim();
1561  String diagPipeName = textDiagCommunication.getText().trim();
1562  if (diagPipeName.isEmpty()) {
1563  this.runtimeManager = RuntimeManagerFactory.CreatePipeRuntimeManager(rtPipeName);
1564  } else {
1565  this.runtimeManager = RuntimeManagerFactory.CreatePipeRuntimeManager(rtPipeName, diagPipeName);
1566  }
1567 
1568  PrintText("Pipe Runtime Manager (MinBinVersion: " + RuntimeConfig.GetInstance().GetMinBinVersion() + ") created");
1569  }
1570 
1571  statusInitializeRuntimeManager = String.format(
1572  "Created %s Runtime Manager (MinBinVersion: %s)"
1573  , this.comboBoxCommunicationType.getValue()
1574  , RuntimeConfig.GetInstance().GetMinBinVersion()
1575  );
1576  PrintText(statusInitializeRuntimeManager);
1577  } catch (Exception ex) {
1578  PrintText(ex.getMessage());
1579  PrintText("No new Runtime Manager will be created");
1580  this.runtimeManager = null;
1581  }
1582  }
1583 
1584  private void UpdateTraceLevel() {
1585  TraceLevels traceLevel = TraceLevels.values()[comboBoxTraceLevel.getSelectionModel().getSelectedIndex()];
1586  RuntimeConfig.GetInstance().SetTraceLevel(traceLevel);
1587  }
1588 
1589  private void UpdateTraceFolder() {
1590  RuntimeConfig.GetInstance().SetTraceFolder(textTracePath.getText());
1591  PrintText("Set TraceFolder to: " + textTracePath.getText());
1592  }
1593 
1594  private void ProcedurePending(IRuntimeContext runtimeContext) {
1595  this.PrintText(String.format("ProcedurePending(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1596  this.UpdateExecutionState(runtimeContext);
1597  this.ShowConnectionStateMessage(runtimeContext);
1598  }
1599 
1600  private void UpdateTraceFileMaxCount() {
1601  try {
1602  int traceFileMaxCount = Integer.parseInt(txtTraceFileMaxCount.getText());
1603  RuntimeConfig.GetInstance().SetTraceFileMaxCount(traceFileMaxCount);
1604  } catch (java.lang.Exception e) {
1605  PrintText(e.getMessage());
1606  }
1607 
1608  PrintText("TraceFileMaxCount is " + Integer.toString(RuntimeConfig.GetInstance().GetTraceFileMaxCount()));
1609  }
1610 
1611  private void UpdateTraceFileMaxSize() {
1612  try {
1613  int traceFileMaxSize = Integer.parseInt(txtTraceFileMaxSize.getText());
1614  RuntimeConfig.GetInstance().SetTraceFileMaxSize(traceFileMaxSize);
1615  } catch (java.lang.Exception e) {
1616  PrintText(e.getMessage());
1617  }
1618 
1619  PrintText("TraceFileMaxSize is " + Integer.toString(RuntimeConfig.GetInstance().GetTraceFileMaxSize()));
1620  }
1621 
1622  public void ProcedureStarted(IRuntimeContext runtimeContext) {
1623  synchronized (eventListenerLock) {
1624  this.PrintText(String.format("ProcedureStarted(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1625 
1626  String procedureName = runtimeContext.GetProcedure().GetFullName();
1627 
1628  this.PrintText(procedureName + " - Started");
1629  this.UpdateExecutionState(runtimeContext);
1630  DisableExecutionButtons();
1631  this.buttonStop.setDisable(false);
1632  AddRuntimeContext(runtimeContext);
1633  this.buttonPause.setDisable(IsPauseDisabled());
1634 
1635  }
1636  }
1637 
1638  private void DisableExecutionButtons() {
1639  if (!checkBoxAsynchron.isSelected()) {
1640  this.buttonExecuteMain.setDisable(true);
1641  this.btnExecuteProcedureSelected.setDisable(true);
1642  }
1643  }
1644 
1645  private void ProcedurePaused(IRuntimeContext runtimeContext, ExecutionStateChangeReason reason) {
1646  this.buttonPause.setDisable(IsPauseDisabled());
1647  this.buttonContinue.setDisable(reason == ExecutionStateChangeReason.Explicit ? IsContinueDisabled() : true);
1648  this.PrintText(String.format("ProcedurePaused(%s) ExecutionState(%s) ExecutionStateChangeReason(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString(), reason.toString()));
1649  this.UpdateExecutionState(runtimeContext);
1650  if (reason == ExecutionStateChangeReason.UnexpectedDiagConnectionState) {
1651  this.ShowConnectionStateMessage(runtimeContext);
1652  }
1653  }
1654 
1655  private void ProcedureContinued(IRuntimeContext runtimeContext) {
1656  this.buttonPause.setDisable(IsPauseDisabled());
1657  this.buttonContinue.setDisable(IsContinueDisabled());
1658  this.PrintText(String.format("ProcedureContinued(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1659  this.UpdateExecutionState(runtimeContext);
1660 
1661  }
1662 
1663  public void ProcedureAborted(IRuntimeContext runtimeContext) {
1664  synchronized (eventListenerLock) {
1665  String procedureName = runtimeContext.GetProcedure().GetFullName();
1666 
1667  if (runtimeContext.HasRuntimeException()) {
1668  PrintText("Runtime exception: " + runtimeContext.GetRuntimeException().getMessage());
1669  }
1670 
1671  if (runtimeContext.HasOtxException()) {
1672  PrintText("Otx exception: " + runtimeContext.GetOtxException().getMessage());
1673  }
1674 
1675  this.PrintText(String.format("ProcedureAborted(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1676 
1677  EnableExecutionButton();
1678  FireAlertSound();
1679  cyclicExecuteAsyncIsProcessing = false;
1680  RemoveRuntimeContext(runtimeContext);
1681  this.buttonPause.setDisable(IsPauseDisabled());
1682  this.buttonContinue.setDisable(IsContinueDisabled());
1683  this.UpdateExecutionState(runtimeContext);
1684  }
1685  }
1686 
1687  private void UpdateExecutionState(IRuntimeContext context) {
1688  if (context != null) {
1689  switch (context.GetExecutionState()) {
1690  case Running:
1691  case Pending:
1692  UpdateExecutionStateButtons(true);
1693  break;
1694 
1695  case Paused:
1696  break;
1697 
1698  case Finished:
1699  case Stopped:
1700  case Aborted:
1701  case Timeout:
1702  UpdateExecutionStateButtons(false);
1703  this.SetIconStateChanged(this.labelBatteryState, "/IconBattery16.png");
1704  this.SetIconStateChanged(this.labelIgnitionState, "/IconIgnition16.png");
1705  break;
1706  default:
1707  break;
1708  }
1709  }
1710  }
1711 
1712  @FXML
1713  private void buttonCheckBatteryIgnition_Click(ActionEvent event) {
1714  CheckBatteryIgnitionState(this.runtimeManager);
1715  }
1716 
1717  private void UpdateExecutionStateButtons(boolean wasExecuted) {
1718  if (this.useConnectionState) {
1719  this.labelTimeout.setDisable(wasExecuted);
1720  this.textBoxTimeout.setDisable(wasExecuted);
1721  this.checkBoxUseConnectionState.setDisable(wasExecuted);
1722  this.labelExpectedState.setDisable(wasExecuted);
1723  this.checkBoxIgnition.setDisable(wasExecuted);
1724  this.labelPollingTime.setDisable(wasExecuted);
1725  this.textBoxPollingTime.setDisable(wasExecuted);
1726  this.labelVoltageThreshold.setDisable(wasExecuted);
1727  this.textBoxBatteryVoltageThreshold.setDisable(wasExecuted);
1728  this.buttonCheckBatteryIgnition.setDisable(wasExecuted);
1729  }
1730 
1731  if (wasExecuted) {
1732  if (!checkBoxAsynchron.isSelected()) {
1733  this.buttonExecuteMain.setDisable(true);
1734  this.btnExecuteProcedureSelected.setDisable(true);
1735  }
1736 
1737  this.buttonStop.setDisable(false);
1738  } else {
1739  EnableExecutionButton();
1740 
1741  this.buttonStop.setDisable(true);
1742  }
1743  }
1744 
1745  private void DiagConnectionStateChanged(ClampState batteryState, ClampState ignitionState) {
1746  this.PrintText(String.format("Event DiagConnectionStateChanged occurred - BatteryState = %s, IgnitionState = %s", batteryState.toString(), ignitionState.toString()));
1747  SetBatteryIgnitionState(batteryState, ignitionState);
1748  }
1749 
1750  public void FireAlertSound() {
1751  final Runnable runnable = (Runnable) Toolkit.getDefaultToolkit().getDesktopProperty("win.sound.default");
1752 
1753  if (runnable != null) {
1754  runnable.run();
1755  }
1756  }
1757 
1758  public void ProcedureFinished(IRuntimeContext runtimeContext) {
1759  synchronized (eventListenerLock) {
1760  String procedureName = runtimeContext.GetProcedure().GetFullName();
1761  String parameterOutput;
1762 
1763  for (IProcedureParameter procedureParameter :
1764  runtimeContext.GetProcedure().GetParameters()) {
1765 
1766  parameterOutput = "Parameter Changed - " +
1767  procedureParameter.GetName() + "(" + procedureParameter.GetDataType() + ") = ";
1768 
1769  if (procedureParameter.GetValue() != null) {
1770  parameterOutput += ShortenedValueString(procedureParameter);
1771  } else {
1772  parameterOutput += "null";
1773  }
1774 
1775  this.PrintText(parameterOutput);
1776  }
1777 
1778  UpdateTableParameters(runtimeContext.GetProcedure());
1779  this.PrintText(String.format("ProcedureFinished(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1780 
1781  if (!this.checkBoxCyclic.isSelected()) {
1782 
1783  EnableExecutionButton();
1784  }
1785 
1786  this.UpdateExecutionState(runtimeContext);
1787  cyclicExecuteAsyncIsProcessing = false;
1788 
1789  RemoveRuntimeContext(runtimeContext);
1790  this.buttonPause.setDisable(IsPauseDisabled());
1791  this.buttonContinue.setDisable(IsContinueDisabled());
1792 
1793  }
1794  }
1795 
1796  public void ProcedureStopped(IRuntimeContext runtimeContext) {
1797  synchronized (eventListenerLock) {
1798  this.PrintText(String.format("ProcedureStopped(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1799 
1800  this.buttonExecuteMain.setDisable(false);
1801  this.btnExecuteProcedureSelected.setDisable(false);
1802  RemoveRuntimeContext(runtimeContext);
1803  this.buttonPause.setDisable(IsPauseDisabled());
1804  this.buttonContinue.setDisable(IsContinueDisabled());
1805 
1806  EnableExecutionButton();
1807  cyclicExecuteAsyncIsProcessing = false;
1808  this.UpdateExecutionState(runtimeContext);
1809  }
1810  }
1811 
1812  private void ProcedureTimeout(IRuntimeContext runtimeContext) {
1813  this.PrintText(String.format("ProcedureTimeout(%s) ExecutionState(%s)", runtimeContext.GetProcedure().GetFullName(), runtimeContext.GetExecutionState().toString()));
1814 
1815  this.buttonExecuteMain.setDisable(false);
1816  EnableExecutionButton();
1817  RemoveRuntimeContext(runtimeContext);
1818  this.buttonPause.setDisable(IsPauseDisabled());
1819  this.buttonContinue.setDisable(IsContinueDisabled());
1820  cyclicExecuteAsyncIsProcessing = false;
1821 
1822  this.UpdateExecutionState(runtimeContext);
1823  }
1824 
1825  private void EnableExecutionButton() {
1826  if (project != null && project.GetMainProcedure() != null) {
1827  this.buttonExecuteMain.setDisable(false);
1828  }
1829 
1830  this.btnExecuteProcedureSelected.setDisable(false);
1831  }
1832 
1833  private void InOutParameterValueChanged(IRuntimeContext iRuntimeContext, IProcedureInOutParameter parameter) {
1834 
1835  try {
1836  String message = "Parameter '"
1837  + parameter.GetName()
1838  + "' new value = " + ShortenedValueString(parameter);
1839  PrintText(message);
1840  UpdateTableParameters(parameter);
1841  } catch (Exception ex) {
1842  PrintText(ex.getMessage());
1843  }
1844 
1845  try {
1846  Thread.sleep(1);
1847  } catch (InterruptedException ignored) {
1848 
1849  }
1850 
1851  }
1852 
1853  private String ShortenedValueString(IProcedureParameter parameter) {
1854  try {
1855  String valueStr = ValueConverter.Value2String(parameter.GetValue());
1856  if (valueStr.length() > VALUE_STRING_MAX_LENGTH)
1857  return valueStr.substring(0, VALUE_STRING_MAX_LENGTH) + "...";
1858  return valueStr;
1859  }
1860  catch (Exception ex)
1861  {
1862  }
1863 
1864  return "";
1865  }
1866 
1867  private String ShortenedValueString(Object value) {
1868  if (value == null) {
1869  return "null";
1870  }
1871 
1872  String valueStr = ValueConverter.Value2String(value);
1873  if (valueStr.length() > VALUE_STRING_MAX_LENGTH)
1874  return valueStr.substring(0, VALUE_STRING_MAX_LENGTH) + "...";
1875  return valueStr;
1876  }
1877 
1878  private void CheckCustomImplRadioButtonGroup() {
1879  if (radioButtonDefaultImplementation.isSelected()) {
1880  if (this.project != null) {
1881  customScreenImplementation.RemoveKeyDownListener(keyDownListener);
1882  customScreenImplementation.AddKeyDownListener(keyDownListener);
1883  }
1884 
1885  stateVariableImplementation.AddStateVariableValueChangedHandler(this::StateVariableValueChange);
1886  contextVariableImplementation.AddContextVariableReadHandler(this::ContextVariableRead);
1887 
1888  runtimeManager.SetCustomImplementation(customScreenImplementation);
1889  runtimeManager.SetCustomImplementation(contextVariableImplementation);
1890  runtimeManager.SetCustomImplementation(stateVariableImplementation);
1891  runtimeManager.SetCustomImplementation(measureImplementation);
1892  runtimeManager.SetCustomImplementation(serviceProviderImplementation);
1893  } else if (radioButtonOutputWindow.isSelected()) {
1894 
1895  runtimeManager.SetCustomImplementation(loggingOutputImpl);
1896  runtimeManager.SetCustomImplementation(basicScreenOutputImpl);
1897  runtimeManager.SetCustomImplementation(customScreenOutputImpl);
1898  runtimeManager.SetCustomImplementation(contextVariableOutputImpl);
1899  runtimeManager.SetCustomImplementation(stateVariableOutputImpl);
1900  runtimeManager.SetCustomImplementation(measureOutputImpl);
1901  runtimeManager.SetCustomImplementation(i18nOutput);
1902  runtimeManager.SetCustomImplementation(sqlOutput);
1903  runtimeManager.SetCustomImplementation(serviceProviderOutputImpl);
1904  } else {
1905  runtimeManager.SetCustomImplementation((ILoggingImplementation) null);
1906  runtimeManager.SetCustomImplementation((IBasicScreenImplementation) null);
1907  runtimeManager.SetCustomImplementation((ICustomScreenImplementation) null);
1908  runtimeManager.SetCustomImplementation((IContextVariableImplementation) null);
1909  runtimeManager.SetCustomImplementation((IStateVariableImplementation) null);
1910  runtimeManager.SetCustomImplementation((IMeasureImplementation) null);
1911  runtimeManager.SetCustomImplementation((Ii18nImplementation) null);
1912  runtimeManager.SetCustomImplementation((ISqlImplementation) null);
1913  runtimeManager.SetCustomImplementation((IExternalServiceProviderImplementation) null);
1914  }
1915 
1916  PrintText("Set up custom implementation finished");
1917  }
1918 
1919  private SampleConstants.CustomImplType GetCustomImplType() {
1920 
1921  if (radioButtonOutputWindow.isSelected())
1922  return SampleConstants.CustomImplType.OutputImpl;
1923 
1924  if (radioButtonNoCustomImplementation.isSelected())
1925  return SampleConstants.CustomImplType.NoCustom;
1926 
1927  return SampleConstants.CustomImplType.DefaultCustomImpl;
1928  }
1929 
1930  private void ExecuteProcedure() {
1931  try {
1932 
1933  if (runtimeManager != null && procedureWillExecute != null) {
1934  buttonStop.setDisable(false);
1935 
1936  CheckBatteryIgnitionState(this.runtimeManager);
1937 
1938  if (checkBoxCyclic.isSelected()) {
1939  ExecuteCyclic();
1940  } else if (checkBoxAsynchron.isSelected()) {
1941  runtimeManager.ExecuteAsync(textRuntimeName.getText().trim(), procedureWillExecute, this.expectedConnectionState, GetTimeout());
1942  } else {
1943  ExecuteNotAsync();
1944  }
1945  }
1946  } catch (Exception ex) {
1947  PrintText("Execute failed: " + ex.getMessage());
1948  UpdateButtonStateAfterThrowException();
1949  }
1950  }
1951 
1952  private void UpdateButtonStateAfterThrowException() {
1953  this.buttonExecuteMain.setDisable(checkBoxCyclic.isSelected());
1954  this.btnExecuteProcedureSelected.setDisable(checkBoxCyclic.isSelected());
1955 
1956  UpdateExecutionStateButtons(false);
1957  this.buttonPause.setDisable(IsPauseDisabled());
1958  this.buttonContinue.setDisable(IsContinueDisabled());
1959 
1960  this.SetIconStateChanged(this.labelBatteryState, "/IconBattery16.png");
1961  this.SetIconStateChanged(this.labelIgnitionState, "/IconIgnition16.png");
1962  }
1963 
1964  private void ExecuteNotAsync() {
1965 
1966  Thread thread = new Thread(() -> {
1967  try {
1968  runtimeManager.Execute(textRuntimeName.getText().trim(), procedureWillExecute, this.expectedConnectionState, GetTimeout());
1969  } catch (Exception ex) {
1970  PrintText("Execute failed: " + ex.getMessage());
1971  this.UpdateButtonStateAfterThrowException();
1972  }
1973  });
1974  thread.setName("Execute");
1975  thread.setDaemon(true);
1976  thread.start();
1977  }
1978 
1979  private void ExecuteCyclic() {
1980  cyclic = 1;
1981 
1982  Thread thread = new Thread(() -> {
1983  try {
1984  DoCyclic();
1985  } catch (Exception e) {
1986  e.printStackTrace();
1987  PrintText("ExecuteCyclic failed: " + e.getMessage());
1988  }
1989  });
1990  thread.setName("ExecuteCyclic");
1991  thread.setDaemon(true);
1992  thread.start();
1993  }
1994 
1995  private void DoCyclic() throws InterruptedException {
1996  do {
1997  cyclicExecuteAsyncIsProcessing = true;
1998  CheckBatteryIgnitionState(this.runtimeManager);
1999  if (this.checkBoxAsynchron.isSelected()) {
2000  IRuntimeContext runtimeContext = runtimeManager.ExecuteAsync(textRuntimeName.getText().trim(), procedureWillExecute, this.expectedConnectionState, GetTimeout());
2001  //Let it breaks a little bit to avoid freezing the GUI.
2002  Thread.sleep(50);
2003  } else {
2004  // TODO: why create a context here?
2005  IRuntimeContext runtimeContext = runtimeManager.Execute(
2006  textRuntimeName.getText().trim()
2007  , procedureWillExecute
2008  , this.expectedConnectionState, GetTimeout()
2009  );
2010  }
2011  cyclic++;
2012 
2013  if (this.checkBoxCyclicReload.isSelected()) {
2014  while (cyclicExecuteAsyncIsProcessing) {
2015  Thread.sleep(50);
2016  }
2017  this.LoadContextFile();
2018  }
2019 
2020  Platform.runLater(() -> {
2021  if (this.checkBoxCyclic.isSelected()) {
2022  this.checkBoxCyclic.setText("Cyclic (" + cyclic + ")");
2023  } else {
2024  this.checkBoxCyclic.setText("Cyclic");
2025  }
2026  });
2027 
2028  } while (checkBoxCyclic.isSelected());
2029  }
2030 
2031  private void UpdateTable(IProcedure procedure) {
2032 
2033  if (procedure == null || procedure.GetParameters() == null) {
2034  return;
2035  }
2036  UpdateTableParameters(procedure);
2037  IDocument document = procedure.GetDocument();
2038 
2039  if (document != null) {
2040  ArrayList<String> addedDocuments = new ArrayList<String>();
2041  UpdateTableContextVariables(document, false, addedDocuments);
2042  addedDocuments.clear();
2043  UpdateTableStateVariables(document, false, addedDocuments);
2044  }
2045  }
2046 
2047  private void UpdateTableParameters(IProcedure procedure) {
2048  for (IProcedureParameter param : procedure.GetParameters()) {
2049  UpdateTableParameters(param);
2050  }
2051  }
2052 
2053  private void UpdateTableParameters(IProcedureParameter param) {
2054 
2055  if (param == null) {
2056  return;
2057  }
2058 
2059  boolean updateParam = false;
2060 
2061  //Update existed items
2062  ObservableList<CustomTableItem> items = tableParameter.getItems();
2063  for (CustomTableItem row : items) {
2064 
2065  // && row.getValue() != null
2066  if (param.GetName().equals(row.getName())) {
2067 
2068  synchronized (tableParameterLock) {
2069  row.setModel(param);
2070  updateParam = true;
2071  break;
2072  }
2073  }
2074  }
2075 
2076  //Add parameter
2077  if (!updateParam) {
2078 
2079  CustomTableItem newRow = new CustomTableItem(param);
2080  items.add(newRow);
2081  }
2082 
2083  tableParameter.refresh();
2084  }
2085 
2086  private void UpdateTableContextVariables(IDocument document, Boolean withPrefix, ArrayList<String> addedDocuments) {
2087  if (addedDocuments.contains(document.GetFullName())) {
2088  return;
2089  }
2090 
2091  addedDocuments.add(document.GetFullName());
2092 
2093  for (IContextVariable context : document.GetContextVariables()) {
2094  if (context == null) {
2095  return;
2096  }
2097 
2098  boolean updateContext = false;
2099 
2100  //Update existed items
2101  for (int i = 0; i < tableContextVariables.getItems().size(); i++) {
2102 
2103  CustomTableItem row = tableContextVariables.getItems().get(i);
2104  String nameContext = withPrefix ? document.GetFullName() : document.GetName();
2105  if (nameContext.equals(row.getName()) && row.getValue() != null) {
2106  if (this.radioButtonDefaultImplementation.isSelected()) {
2107  Object value = this.contextVariableImplementation.GetValue(
2108  null
2109  , context
2110  , null
2111  );
2112  row.setValue(value);
2113  } else {
2114  row.setModel(context);
2115  }
2116 
2117  updateContext = true;
2118  break;
2119  }
2120  }
2121 
2122  if (!updateContext) {
2123 
2124  CustomTableItem newRow = new CustomTableItem(context, withPrefix);
2125  if (this.radioButtonDefaultImplementation.isSelected()) {
2126  Object value = context.GetInitValue();
2127  newRow.setValue(value);
2128  }
2129  tableContextVariables.getItems().add(newRow);
2130  }
2131  }
2132 
2133  try {
2134  for (IDocument importDoc : document.GetImports()) {
2135  UpdateTableContextVariables(importDoc, true, addedDocuments);
2136  }
2137  } catch (Exception e) {
2138  PrintText("Exception" + e.getMessage());
2139  }
2140  }
2141 
2142  public void ContextVariableRead(IContextVariable contextVariable, Object value) {
2143  String mappingStr =
2144  contextVariable.GetMappingName().isEmpty()
2145  ? ""
2146  : (
2147  " [MappedTo: " + contextVariable.GetMappingName() + (contextVariable.GetMappingIndex() > -1
2148  ? ("[" + contextVariable.GetMappingIndex() + "]")
2149  : "") + "]"
2150  );
2151 
2152  String outputLog = "ContextVariableRead(" +
2153  contextVariable.GetDataType() + " " +
2154  contextVariable.GetDocument().GetFullName() + "." +
2155  contextVariable.GetName() + mappingStr + " = " +
2156  ShortenedValueString(value) + ")";
2157 
2158  PrintText(outputLog);
2159  }
2160 
2161  public void StateVariableValueChange(IStateVariable stateVariable, Object value) {
2162  String mappingStr =
2163  stateVariable.GetMappingName().isEmpty()
2164  ? ""
2165  : (
2166  " [MappedTo: " + stateVariable.GetMappingName() + (stateVariable.GetMappingIndex() > -1
2167  ? ("[" + stateVariable.GetMappingIndex() + "]")
2168  : "") + "]"
2169  );
2170 
2171  String outputLog = "StateVariableChanged(" +
2172  stateVariable.GetDataType() + " " +
2173  stateVariable.GetDocument().GetFullName() + "." +
2174  stateVariable.GetName() + mappingStr + " = " +
2175  ShortenedValueString(value) + ")";
2176 
2177  PrintText(outputLog);
2178  UpdateTableStateVariables(stateVariable); // TODO: StateVariable value in Object will never change!! Review this
2179  }
2180 
2181  private void UpdateTableStateVariables(IDocument document, Boolean withPrefix, ArrayList<String> addedDocuments) {
2182  if (addedDocuments.contains(document.GetFullName())) {
2183  return;
2184  }
2185 
2186  addedDocuments.add(document.GetFullName());
2187 
2188  for (IStateVariable state : document.GetStateVariables()) {
2189  if (state == null) {
2190  return;
2191  }
2192  CustomTableItem newRow = new CustomTableItem(state, withPrefix);
2193  tableStateVariables.getItems().add(newRow);
2194  }
2195 
2196  try {
2197  for (IDocument importDoc : document.GetImports()) {
2198  UpdateTableStateVariables(importDoc, true, addedDocuments);
2199  }
2200  } catch (Exception e) {
2201  PrintText("Exception" + e.getMessage());
2202  }
2203  }
2204 
2205  private void UpdateTableStateVariables(IStateVariable state) {
2206  if (state == null) {
2207  return;
2208  }
2209 
2210  //Update existed items
2211  for (int i = 0; i < tableStateVariables.getItems().size(); i++) {
2212 
2213  CustomTableItem row = tableStateVariables.getItems().get(i);
2214 
2215  if (state == row.getModel() && row.getValue() != null) {
2216  if (radioButtonDefaultImplementation.isSelected()) {
2217  Object value = this.stateVariableImplementation.GetValue(state);
2218  row.setValue(value);
2219  } else {
2220  row.setModel(state);
2221  }
2222  break;
2223  }
2224  }
2225  }
2226 
2227  private void LoadContextFile() {
2228 
2229  if (txtFilePath.getText().isEmpty())
2230  return;
2231 
2232  try {
2233  Path filePath = Paths.get(txtFilePath.getText());
2234  if (Files.notExists(filePath)) {
2235  PrintText("File is not exist!");
2236  return;
2237  }
2238 
2239  ClearSamepleGUI();
2240  this.project = null;
2241  this.playerProject = null;
2242  String fileExtension = FileUtil.GetExtension(filePath);
2243  if (fileExtension.contains(PTX_EXTENSION)) {
2244  this.project = LoadPtx();
2245 
2246  if (this.project != null) {
2247  ClearCustomImplementationsCaches();
2248 
2249  PrintText("Load project " + project.GetName() + " successfully");
2250 
2251  this.LoadPackage();
2252  SaveDirectoryOnSuccessLoad(filePath.getParent());
2253  ReadSettings(this.project.GetSettings());
2254  }
2255  } else if (fileExtension.contains(PPX_EXTENSION)) {
2256  this.playerProject = LoadPpx();
2257 
2258  if (this.playerProject != null) {
2259  ClearCustomImplementationsCaches();
2260 
2261  PrintText("Load player " + playerProject.GetName() + " successfully");
2262 
2263  for (IProject project :
2264  playerProject.GetProjects()) {
2265  this.project = project;
2266  this.LoadPackage();
2267  }
2268 
2269  SaveDirectoryOnSuccessLoad(filePath.getParent());
2270  ReadSettings(this.playerProject.GetSettings());
2271  }
2272  } else {
2273  FireAlertSound();
2274  PrintText("Could not find supported file.");
2275  }
2276 
2277  } catch (Exception e) {
2278  PrintException(e);
2279  }
2280  }
2281 
2282  private void PrintException(Exception e) {
2283  FireAlertSound();
2284 
2285  // If runtimeManager is null and an exception is thrown, a license issue may be present.
2286  if (this.runtimeManager == null) {
2287  PrintText("RuntimeManager is not created, please check or set your license.");
2288  PrintText("Load project fail: RuntimeManager is not created.");
2289  return;
2290  }
2291 
2292  if (e.getMessage().contains("The file cannot be decrypted")) {
2293  PrintText("The file cannot be decrypted. Either the password is wrong or the file has a wrong format or is corrupt. Please check the password or the file!");
2294  return;
2295  }
2296 
2297  PrintText(e.getMessage());
2298  }
2299 
2300  private void ClearSamepleGUI() {
2301  this.treeViewOtxProject.getRoot().getChildren().clear();
2302  this.tableProjectSetting.getItems().clear();
2303  }
2304 
2305  private void ClearCustomImplementationsCaches() {
2306  this.contextVariableImplementation.ClearCaches();
2307 
2308  this.contextVariableOutputImpl.ClearCaches();
2309 
2310  this.stateVariableImplementation.ClearCaches();
2311 
2312  //TODO: if(this.stateVariableOutputImpl != null)
2313  }
2314 
2315  private void SaveDirectoryOnSuccessLoad(Path directoryToSave) {
2316  if (directoryToSave.toString().equals(lastOpenedDirectory))
2317  return;
2318 
2319  lastOpenedDirectory = directoryToSave.toString().intern();
2320  }
2321 
2322  private void LoadPackage() {
2323 
2324  IPackage[] packages = project.GetPackages();
2325 
2326  if (packages == null) {
2327  IDocument document = project.GetStartupDocument();
2328  this.treeViewOtxProject.getRoot().getChildren().add(CreateDocumentNode(document));
2329  } else {
2330  StringBuilder stringBuilder = new StringBuilder();
2331  stringBuilder.append(project.GetName());
2332 
2333  if (!project.GetVersion().isEmpty()) {
2334  stringBuilder.append(" (")
2335  .append(project.GetVersion())
2336  .append(")");
2337  }
2338 
2339  Node rootImage = new ImageView(new Image(getClass().getResourceAsStream(PROJECT_ICON)));
2340  CustomTreeItem projectRoot = new CustomTreeItem(project);
2341  projectRoot.setValue(stringBuilder.toString());
2342  projectRoot.setGraphic(rootImage);
2343 
2344  for (IPackage item : packages) {
2345  projectRoot.getChildren().add(CreatePackageNode(item));
2346  }
2347 
2348  projectRoot.setExpanded(true);
2349  this.treeViewOtxProject.getRoot().getChildren().add(projectRoot);
2350  }
2351 
2352  this.treeViewOtxProject.getSelectionModel().select(startupNode);
2353  }
2354 
2355 
2356  private CustomTreeItem CreateDocumentNode(IDocument document) {
2357  CustomTreeItem documentNode = new CustomTreeItem(document);
2358  String value = document.GetName();
2359 
2360  if (document.IsStartup()) {
2361  value += " (Start up)";
2362  }
2363  documentNode.setValue(value);
2364 
2365  for (IProcedure procedure : document.GetProcedures()) {
2366  CustomTreeItem procedureNode = CreateProcedureNode(procedure);
2367  documentNode.getChildren().add(procedureNode);
2368 
2369  if (document.IsStartup() && procedure.GetName().equals(MAIN_PROCEDURE_NAME)) {
2370  startupNode = procedureNode;
2371  buttonExecuteMain.setDisable(false);
2372  } else if (startupNode == null) {
2373  startupNode = procedureNode;
2374  }
2375  }
2376 
2377  final Node documentImage = new ImageView(new Image(getClass().getResourceAsStream(DOCUMENT_ICON)));
2378  documentNode.setGraphic(documentImage);
2379  documentNode.setExpanded(true);
2380  return documentNode;
2381  }
2382 
2383  private CustomTreeItem CreateProcedureNode(IProcedure procedure) {
2384  CustomTreeItem procedureNode = new CustomTreeItem(procedure);
2385  procedureNode.setValue(procedure.GetName());
2386 
2387  Node procedureImage = new ImageView(new Image(getClass().getResourceAsStream(PROCEDURE_ICON)));
2388  procedureNode.setGraphic(procedureImage);
2389  procedureNode.setExpanded(true);
2390 
2391  if (checkBoxCyclicReload.isSelected() &&
2392  procedureWillExecute != null &&
2393  procedureWillExecute.GetFullName().equals(procedure.GetFullName())) {
2394  procedureWillExecute = procedure;
2395  }
2396 
2397  return procedureNode;
2398  }
2399 
2400  private CustomTreeItem CreatePackageNode(IPackage item) {
2401  CustomTreeItem packageNode = new CustomTreeItem(item);
2402  packageNode.setValue(item.GetName());
2403 
2404  for (IDocument doc : item.GetDocuments()) {
2405  packageNode.getChildren().add(CreateDocumentNode(doc));
2406  }
2407 
2408  for (IPackage pac : item.GetPackages()) {
2409  packageNode.getChildren().add(CreatePackageNode(pac));
2410  }
2411 
2412  final Node packageImage = new ImageView(new Image(getClass().getResourceAsStream(PACKAGE_ICON)));
2413  packageNode.setGraphic(packageImage);
2414  packageNode.setExpanded(true);
2415  return packageNode;
2416  }
2417 
2418  private void PrintText(String context) {
2419 
2420  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
2421  LocalDateTime now = LocalDateTime.now();
2422 
2423  synchronized (printTextLock) {
2424  String itemWillInsert = lineNumber + " " + dtf.format(now) + " " + context;
2425 
2426  Platform.runLater(() -> {
2427  if (lineNumber > 10000) {
2428  listViewOutputText.setItems(FXCollections.observableList(new ArrayList<>()));
2429  buttonCopyRow.setDisable(true);
2430  labelOutputOverflow.setVisible(false);
2431  lineNumber = 0;
2432  }
2433 
2434  List<String> items = listViewOutputText.getItems();
2435  items.add(itemWillInsert + "\n");
2436  listViewOutputText.scrollTo(items.size());
2437  });
2438 
2439  if (lineNumber + 1 >= 7500) {
2440  labelOutputOverflow.setVisible(true);
2441  }
2442 
2443  lineNumber++;
2444 
2445  this.buttonCopyRow.setDisable(false);
2446  }
2447  }
2448 
2449  private IProject LoadPtx() throws IOException {
2450  IProject project = null;
2451 
2452  if (runtimeManager.IsProtected(txtFilePath.getText())) {
2453  project = runtimeManager.LoadPtx(txtFilePath.getText(), txtPassword.getText().trim());
2454  } else {
2455  project = runtimeManager.LoadPtx(txtFilePath.getText());
2456  }
2457 
2458  return project;
2459  }
2460 
2461  private IPlayerProject LoadPpx() {
2462  IPlayerProject playerProject = null;
2463 
2464  if (runtimeManager.IsProtected(txtFilePath.getText())) {
2465  playerProject = runtimeManager.LoadPpx(txtFilePath.getText(), txtPassword.getText().trim());
2466  } else {
2467  playerProject = runtimeManager.LoadPpx(txtFilePath.getText());
2468  }
2469 
2470  return playerProject;
2471  }
2472 
2473  @FXML
2474  private void buttonPause_Click(MouseEvent event) {
2475  synchronized (runtimeContexts) {
2476  for (IRuntimeContext runtimeContext : runtimeContexts) {
2477  if (runtimeContext.GetExecutionState() == ExecutionState.Running) {
2478  runtimeContext.Pause();
2479  }
2480  }
2481  }
2482  }
2483 
2484  @FXML
2485  private void buttonContinue_Click(MouseEvent event) {
2486  synchronized (runtimeContexts) {
2487  for (IRuntimeContext runtimeContext : runtimeContexts) {
2488  if (runtimeContext.GetExecutionState() == ExecutionState.Paused) {
2489  runtimeContext.Continue();
2490  }
2491  }
2492  }
2493  }
2494 
2495  private void AddRuntimeContext(IRuntimeContext context) {
2496  synchronized (runtimeContexts) {
2497  runtimeContexts.add(context);
2498  }
2499  }
2500 
2501  private void RemoveRuntimeContext(IRuntimeContext context) {
2502  synchronized (runtimeContexts) {
2503  runtimeContexts.remove(context);
2504  }
2505  }
2506 
2507  private boolean IsPauseDisabled() {
2508  return !IsAnyRuntimeContextExecutionStateIs(ExecutionState.Running);
2509  }
2510 
2511  private boolean IsContinueDisabled() {
2512  return !IsAnyRuntimeContextExecutionStateIs(ExecutionState.Paused);
2513  }
2514 
2515  private boolean IsAnyRuntimeContextExecutionStateIs(final ExecutionState executionState) {
2516  synchronized (runtimeContexts) {
2517  return runtimeContexts.stream()
2518  .anyMatch(
2519  runtimeContext ->
2520  runtimeContext.GetExecutionState() == executionState
2521  );
2522  }
2523  }
2524 
2525  @FXML
2526  void textBoxTimeout_Action() {
2527  GetTimeout();
2528  }
2529 
2530  private Long GetTimeout() {
2531  long timeout = 0;
2532  try {
2533  timeout = Long.parseLong(this.textBoxTimeout.getText());
2534  if (timeout < 0) {
2535  timeout = 0;
2536  this.textBoxTimeout.setText("0");
2537  }
2538  } catch (NumberFormatException nfe) {
2539  this.textBoxTimeout.setText("0");
2540  }
2541 
2542  return timeout;
2543  }
2544 
2545  private Stage CreateLicenseStage() throws IOException {
2546  FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/LicenseForm.fxml"));
2547  Stage licenseInputFormStage = fxmlLoader.load();
2548 
2549  LicenseFormController licenseFormController = fxmlLoader.getController();
2550  licenseFormController.setReloadRuntimeManager(this::ReloadRuntimeMangerAfterSetLicense);
2551 
2552  licenseInputFormStage.getIcons().add(new Image("/Key10.png"));
2553  licenseInputFormStage.initModality(Modality.APPLICATION_MODAL);
2554  licenseInputFormStage.setTitle("License");
2555  licenseInputFormStage.setResizable(false);
2556 
2557  return licenseInputFormStage;
2558  }
2559 
2560  public void ReloadRuntimeMangerAfterSetLicense() throws InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
2561  CreateRuntimeManagerAndSetConfig();
2562  }
2563 
2564  public void buttonLicense_Click() throws IOException {
2565  Stage licenseInputFormStage = this.CreateLicenseStage();
2566  licenseInputFormStage.showAndWait();
2567  }
2568 }
Converts OTX Value to String and vice versa.
Definition: ValueConverter.java:17
Class to manage the OTX-Runtime API licenses.
Definition: LicenseManager.java:9
Contains Projects.
Definition: IPlayerProject.java:10
Contains Packages and settings.
Definition: IProject.java:15
Package containing all interfaces for custom implementations.
Definition: ConfirmationTypes.java:1
Package contains all supported data types.
Definition: BlackBox.java:1
Package containing all objects related to licensing.
Definition: IpcLicenseCheckerBase.java:1
Package for browsing at OTX data structure.
Definition: IContextVariable.java:1
Package containing main entries: IProject and IPlayerProject.
Definition: IPlayerProject.java:1
Package containing the programming interface for browsing and execution of OTX procedures in own appl...
Definition: ApiConstants.java:1
Package containing all objects for browsing and execution of OTX procedures.
Definition: opentestsystem.otx.runtime2.api/src/main/java/opentestsystem/otx/runtime/package-info.java:4
Package containing all objects which are standardized according to ISO 13209 (OTX)
Package containing all objects related to testing inside automotive industry.