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