Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OP-312 telemetry module #876

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rsc/settings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ LABMULTIPLEINSERT=yes
INTERNALPHARMACIES=yes
MERGEFUNCTION=yes
SMSENABLED=no
TELEMETRYENABLED=no
INTERNALVIEWER=yes
MAINMENUALWAYSONTOP=no
RECEIPTPRINTER=yes
Expand Down
6 changes: 6 additions & 0 deletions rsc/telemetry.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# enables/disables daemon - valid values: true | false
telemetry.daemon.enabled=true
# number of second to check if it should send a message
telemetry.daemon.thread.loop.seconds=10
# remote data collector server base url
telemetry-gateway-service.base-url=http://localhost:8080
41 changes: 33 additions & 8 deletions src/main/java/org/isf/menu/gui/MainMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
import org.isf.menu.model.UserGroup;
import org.isf.menu.model.UserMenuItem;
import org.isf.sms.service.SmsSender;
import org.isf.telemetry.TelemetryGUI;
import org.isf.telemetry.daemon.TelemetryDaemon;
import org.isf.telemetry.model.Telemetry;
import org.isf.utils.exception.OHServiceException;
import org.isf.utils.exception.gui.OHServiceExceptionUtil;
import org.isf.utils.jobjects.ModalJFrame;
Expand All @@ -64,12 +67,14 @@
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class MainMenu extends JFrame implements ActionListener, Login.LoginListener, SubMenu.CommandListener {
public class MainMenu extends JFrame implements ActionListener, Login.LoginListener, SubMenu.CommandListener, TelemetryGUI.TelemetryListener {

private static final long serialVersionUID = 7620582079916035164L;
public static final String ADMIN_STR = "admin";
private boolean flag_Xmpp;
private boolean flag_Sms;
private boolean flagSms;
private boolean flagTelemetry;
private Telemetry telemetry;

private static final Logger LOGGER = LoggerFactory.getLogger(MainMenu.class);

Expand Down Expand Up @@ -129,7 +134,7 @@ public int getMinButtonSize() {
public MainMenu() {
myFrame = this;
GeneralData.initialize();
Locale.setDefault(new Locale(GeneralData.LANGUAGE)); //for all fixed options YES_NO_CANCEL in dialogs
Locale.setDefault(new Locale(GeneralData.LANGUAGE)); // for all fixed options YES_NO_CANCEL in dialogs
singleUser = GeneralData.getGeneralData().getSINGLEUSER();
MessageBundle.getBundle();
try {
Expand All @@ -139,12 +144,14 @@ public MainMenu() {
LOGGER.info("Debug: OpenHospital in debug mode.");
}
flag_Xmpp = GeneralData.XMPPMODULEENABLED;
flag_Sms = GeneralData.SMSENABLED;
flagSms = GeneralData.SMSENABLED;

// start connection with SMS service
if (flag_Sms) {
if (flagSms) {
Thread thread = new Thread(new SmsSender());
thread.start();
}

} catch (Exception e) {
singleUser = true; // default for property not found
internalPharmacies = false; // default for property not found
Expand All @@ -160,11 +167,11 @@ public MainMenu() {
// get an user
LOGGER.info("Logging: Multi User mode.");
new Login(this);

if (null == myUser) {
// Login failed
actionExit(2);
}
new TelemetryGUI(this);
}

// get menu items
Expand All @@ -185,8 +192,7 @@ public MainMenu() {
}
new CommunicationFrame();
/*
* Interaction communication= new Interaction();
* communication.incomingChat(); communication.receiveFile();
* Interaction communication= new Interaction(); communication.incomingChat(); communication.receiveFile();
*/
} catch (XMPPException e) {
String message = e.getMessage();
Expand Down Expand Up @@ -268,6 +274,7 @@ public MainMenu() {
// add panel with buttons to frame
MainPanel panel = new MainPanel(this);
add(panel);

pack();

// compute menu position
Expand All @@ -280,6 +287,7 @@ public MainMenu() {
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setAlwaysOnTop(GeneralData.MAINMENUALWAYSONTOP);
myFrame.addWindowListener(new WindowAdapter() {

@Override
public void windowClosing(WindowEvent e) {
actionExit(0);
Expand All @@ -288,6 +296,7 @@ public void windowClosing(WindowEvent e) {

setResizable(false);
setVisible(true);

}

private void actionExit(int status) {
Expand Down Expand Up @@ -408,4 +417,20 @@ public Dimension getPreferredSize() {
public static User getUser() {
return myUser;
}

@Override
public void telemetryInserted(AWTEvent e) {
if (e.getSource() instanceof Telemetry) {
telemetry = (Telemetry) e.getSource();
LOGGER.info("Telemetry: \"{}\" telemetry inserted.", telemetry);
if (null != this.telemetry) {
flagTelemetry = GeneralData.TELEMETRYENABLED;
if (flagTelemetry) {
Thread thread = new Thread(new TelemetryDaemon());
thread.start();
}
}
}

}
}
35 changes: 35 additions & 0 deletions src/main/java/org/isf/telemetry/CheckBoxWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.isf.telemetry;

import javax.swing.JCheckBox;

public class CheckBoxWrapper {

private String id;
private Integer order;
private JCheckBox checkbox;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public Integer getOrder() {
return order;
}

public void setOrder(Integer order) {
this.order = order;
}

public JCheckBox getCheckbox() {
return checkbox;
}

public void setCheckbox(JCheckBox checkbox) {
this.checkbox = checkbox;
}

}
220 changes: 220 additions & 0 deletions src/main/java/org/isf/telemetry/TelemetryGUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package org.isf.telemetry;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.event.EventListenerList;

import org.isf.envdatacollector.AbstractDataCollector;
import org.isf.generaldata.MessageBundle;
import org.isf.menu.gui.MainMenu;
import org.isf.telemetry.manager.TelemetryManager;
import org.isf.telemetry.model.Telemetry;
import org.isf.telemetry.util.TelemetryUtils;
import org.isf.utils.BooleanUtils;
import org.isf.utils.ExceptionUtils;
import org.isf.utils.layout.SpringUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

// estendere JDialog
public class TelemetryGUI extends JDialog {

private static final long serialVersionUID = 891561833857381224L;

private static final Logger LOGGER = LoggerFactory.getLogger(Telemetry.class);
private MainMenu parent;
private EventListenerList telemetryListeners = new EventListenerList();
private Telemetry telemetry;

public TelemetryGUI(MainMenu parent) {
super(parent, MessageBundle.getMessage("angal.login.title"), true);
this.parent = parent;
this.addTelemetryListener(parent);
ApplicationContext springSexyContext = new ClassPathXmlApplicationContext("applicationContext.xml");
TelemetryManager telemetryManager = springSexyContext.getBean(TelemetryManager.class);
TelemetryUtils telemetryUtils = springSexyContext.getBean(TelemetryUtils.class);

Telemetry telemetry = telemetryManager.retrieveSettings();
Map<String, Boolean> settings = telemetry != null && telemetry.getConsentMap() != null ? telemetry.getConsentMap() : new HashMap<>();
List<CheckBoxWrapper> checkboxes = buildPermissionCheckboxes(springSexyContext, settings);
JButton confirmButton = buildConfirmButton(checkboxes, telemetryManager, telemetryUtils);
JButton cancelButton = buildCancelButton(telemetryManager);

add(this.panel(checkboxes, confirmButton, cancelButton));
pack();

Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screensize = kit.getScreenSize();

Dimension mySize = getSize();

setLocation((screensize.width - mySize.width) / 2, (screensize.height - mySize.height) / 2);

setResizable(false);
setVisible(true);
}

public interface TelemetryListener extends EventListener {

void telemetryInserted(AWTEvent e);
}

public void addTelemetryListener(TelemetryListener listener) {
telemetryListeners.add(TelemetryListener.class, listener);
}

private JButton buildConfirmButton(List<CheckBoxWrapper> checkboxes, TelemetryManager telemetryManager, TelemetryUtils telemetryUtils) {
JButton confirmButton = new JButton("Confirm");
confirmButton.addActionListener(buildConfirmationActionListener(checkboxes, telemetryManager, telemetryUtils));
return confirmButton;
}

private JButton buildCancelButton(TelemetryManager telemetryManager) {
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(buildCancelButtonActionListener(telemetryManager));
return cancelButton;
}

/**
* We could load checkboxes information from somewhere (properties file or from other strange places)
*
* @return
*/
private List<CheckBoxWrapper> buildPermissionCheckboxes(ApplicationContext springSexyContext, Map<String, Boolean> consentMap) {

Map<String, AbstractDataCollector> checkboxContractMap = springSexyContext.getBeansOfType(AbstractDataCollector.class);
List<AbstractDataCollector> checkboxContractList = new ArrayList<>(checkboxContractMap.values());
Collections.sort(checkboxContractList, AnnotationAwareOrderComparator.INSTANCE);

List<CheckBoxWrapper> result = new ArrayList<>();

int[] i = { 0 };
checkboxContractList.forEach(springCheckboxConfigurationBean -> {
JCheckBox chb = new JCheckBox(springCheckboxConfigurationBean.getDescription(), springCheckboxConfigurationBean.isSelected(consentMap));
CheckBoxWrapper wrapper = new CheckBoxWrapper();
wrapper.setCheckbox(chb);
wrapper.setId(springCheckboxConfigurationBean.getId());
wrapper.setOrder(Integer.valueOf(i[0]++));
result.add(wrapper);
});

return result;
}

private void fireTelemetryInserted(Telemetry telemetry) {
AWTEvent event = new AWTEvent(telemetry, AWTEvent.RESERVED_ID_MAX + 1) {

private static final long serialVersionUID = 1L;
};

EventListener[] listeners = telemetryListeners.getListeners(TelemetryListener.class);
for (EventListener listener : listeners) {
((TelemetryListener) listener).telemetryInserted(event);
}
}

/**
* Action for confirmation button: inserts for the first time in the telemetry table or updates the existing row
*
* @param permissions
* @param telemetryManager
* @return
*/
private ActionListener buildConfirmationActionListener(List<CheckBoxWrapper> checkboxes, TelemetryManager telemetryManager, TelemetryUtils telemetryUtils) {
return new ActionListener() {

public void actionPerformed(ActionEvent e) {
Map<String, Boolean> consentMap = buildConsentData(checkboxes);
if (this.isReallyEnabled(consentMap)) {
telemetry = telemetryManager.enable(consentMap);
fireTelemetryInserted(telemetry);
try {
telemetryUtils.sendTelemetryData(consentMap);
} catch (RuntimeException f) {
LOGGER.error("Something strange happened: " + f.getMessage());
LOGGER.error(ExceptionUtils.extractStackTrace());
}
} else {
telemetryManager.disable(new HashMap<>());
}
removeTelemetryListener(parent);
dispose();
}

private void removeTelemetryListener(TelemetryListener listener) {
telemetryListeners.remove(TelemetryListener.class, listener);
}

private boolean isReallyEnabled(Map<String, Boolean> cd) {
if (cd == null || cd.isEmpty()) {
return false;
}
return cd.keySet().stream().anyMatch(key -> BooleanUtils.isTrue(cd.get(key)));
}

private Map<String, Boolean> buildConsentData(List<CheckBoxWrapper> permissions) {

Map<String, Boolean> result = new HashMap<>();
permissions.forEach(per -> {
result.put(per.getId(), Boolean.valueOf(per.getCheckbox().isSelected()));
});

return result;
}

};
}

private ActionListener buildCancelButtonActionListener(TelemetryManager telemetryManager) {
return new ActionListener() {

public void actionPerformed(ActionEvent e) {
dispose();
}
};

}

public JPanel panel(List<CheckBoxWrapper> checkboxes, JButton confirmButton, JButton cancelButton) {

JPanel panel = new JPanel(new SpringLayout());

panel.add(new JLabel(MessageBundle.getMessage("angal.common.userid.label")));
checkboxes.forEach(chb -> {
panel.add(chb.getCheckbox());
});
SpringUtilities.makeCompactGrid(panel, checkboxes.size(), 1, 5, 5, 5, 5);

JPanel buttons = new JPanel();
buttons.setLayout(new FlowLayout());
buttons.add(confirmButton);
buttons.add(cancelButton);

setLayout(new BorderLayout(10, 10));
add(panel, BorderLayout.NORTH);
add(buttons, BorderLayout.SOUTH);
return panel;
}

}