org.hwo.pulscounter/src/org/hwo/pulscounter/PulsCounterApplication.java

555 lines
14 KiB
Java

package org.hwo.pulscounter;
import static org.hwo.logging.Logging.log;
import static org.hwo.logging.LogLevel.*;
import java.awt.EventQueue;
import java.awt.Frame;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InvalidPropertiesFormatException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.JFrame;
import org.hsqldb.persist.EventLogInterface;
import org.hwo.StringHelper;
import org.hwo.configuration.ConfigurableObjects;
import org.hwo.io.NewSerialPort.NewSerialPort;
import org.hwo.platform.Platform;
import org.hwo.servicelink.ServiceLink;
import org.hwo.servicelink.ServiceLinkListener;
import org.hwo.pulscounter.device.IDeviceConnector;
import org.hwo.pulscounter.device.ServiceLinkDeviceConnector;
import org.hwo.pulscounter.device.SimulatedCounter;
import org.hwo.pulscounter.ui.AppSettingsListener;
import org.hwo.pulscounter.ui.BatchRunner;
import org.hwo.pulscounter.ui.NewMainWindow;
import org.hwo.scheduler.Scheduler;
public class PulsCounterApplication implements ServiceLinkListener{
static PulsCounterApplication _application;
public static PulsCounterApplication getApplication(){
if (_application == null)
_application = new PulsCounterApplication(null);
return _application;
}
private Properties applicationConfiguration;
private List<IDeviceConnector> deviceConnectors;
private Object uiSynchronization;
private boolean uiIsFinished;
private boolean shouldSaveConfiguration;
private List<PulsCounterApplicationListener>
applicationListeners;
private Vector<String> unseenMessages;
private List<Class<IDeviceConnector>>
interfaceClasses;
private List<IDeviceConnector> interfaces;
private NewSerialPort serialPort;
private ServiceLink serviceLink;
private List<AppSettingsListener> appSettingsListeners;
private boolean snapshotLock;
private SnapshotManager snapshotManager;
private List<ExportSetting> exportSettings;
private Scheduler scheduler;
private String[] channelDescriptions;
public PulsCounterApplication(String[] args) {
/* Initialize Logging Framework */
logStartup();
/* Check... */
if (_application != null){
throw new InstantiationError("Only one Instance of PulsCounterApplication can exist!");
} else {
_application = this;
}
/* Initialize fields... */
uiIsFinished = false;
uiSynchronization = new Object();
deviceConnectors = new ArrayList<>();
applicationListeners = new LinkedList<PulsCounterApplicationListener>();
unseenMessages = new Vector<String>();
interfaceClasses = new ArrayList<>();
interfaces = new ArrayList<>();
/* Prepare for Startup */
loadApplicationConfiguration();
/* Parse Command Line Arguments */
Iterator<String> options = Arrays.asList(args).iterator();
while (options.hasNext()){
String option = options.next();
switch (option){
case "--gui":
if (!options.hasNext()){
log(FATAL,"Argument to --gui is missing");
throw new IllegalArgumentException("Argument to --gui is missing");
} else {
applicationConfiguration.setProperty("ui.class", options.next());
}
break;
case "--batch":
case "-B":
applicationConfiguration.setProperty("ui.class", BatchRunner.class.getCanonicalName());
break;
case "-G":
applicationConfiguration.setProperty("ui.class", NewMainWindow.class.getCanonicalName());
break;
default:
log(WARN,"Unknown command line parameter: %s", option);
}
}
/* Old stuff... */
// this.initialize();
}
private void loadApplicationConfiguration(){
applicationConfiguration = new Properties();
/* Initialize default configuration */
applicationConfiguration.setProperty("ui.class", NewMainWindow.class.getCanonicalName());
applicationConfiguration.setProperty("interface.classes", StringHelper.join(new String[]{
ServiceLinkDeviceConnector.class.getCanonicalName(),
SimulatedCounter.class.getCanonicalName()
}, ","));
try {
/* Try to load configuration from file */
FileInputStream fis = new FileInputStream("synololog.cfg");
applicationConfiguration.loadFromXML(fis);
fis.close();
} catch (InvalidPropertiesFormatException e) {
log(WARN,"synololog.cfg is misformated");
} catch (FileNotFoundException e) {
log(WARN,"synololog.cfg not found");
} catch (IOException e) {
log(ERROR,"I/O Error reading synololog.cfg");
}
}
public Properties getApplicationConfiguration(){
return this.applicationConfiguration;
}
private static void logStartup(){
log("Synololog Application Startup");
log("JAVA Environment: %s (%s)", System.getProperty("java.version"),
System.getProperty("java.vendor"));
log("Operating System: %s [%s] %s", System.getProperty("os.name"),
System.getProperty("os.arch"),
System.getProperty("os.version"));
log("User Environment: %s (%s) (CWD:%s)", System.getProperty("user.name"),
System.getProperty("user.home"),
System.getProperty("user.dir"));
log("Hostname: %s",Platform.getHostName());
log("OS Search Path: %s", System.getenv("PATH"));
}
public void start(){
initialize();
String uiClassName = applicationConfiguration.getProperty("ui.class");
try {
Class uiClazz = PulsCounterApplication.class.getClassLoader().loadClass(uiClassName);
Constructor<?> constructor = uiClazz.getConstructor(PulsCounterApplication.class);
Object ui = (Object) constructor.newInstance(this);
} catch (ClassNotFoundException e) {
log(FATAL,"user interface class could not be loaded [%s] %s",uiClassName,e.getMessage());
} catch (NoSuchMethodException e) {
log(FATAL,"user interface class misses valid constructor [%s] %s",uiClassName,e.getMessage());
} catch (SecurityException e) {
e.printStackTrace();
} catch (Exception e) {
log(FATAL,"user interface class could not be instantiated. [%s] %s",uiClassName,e.getMessage());
e.printStackTrace();
}
waitUiFinished();
try {
shutdown();
} catch (Exception e){
log(e);
}
}
private void initialize(){
String[] interfaceClassNames = applicationConfiguration.getProperty("interface.classes").split(",");
for (String interfaceClassName: interfaceClassNames){
try {
Class<IDeviceConnector> clazz = (Class<IDeviceConnector>)PulsCounterApplication.class.getClassLoader().loadClass(interfaceClassName);
interfaceClasses.add(clazz);
} catch (ClassNotFoundException e) {
log(ERROR,"Interface class could not be loaded: %s",interfaceClassName);
}
}
Integer nIntf = Integer.parseInt(applicationConfiguration.getProperty("interfaces.n","0"));
for (int n=0;n<nIntf;n++){
Class<IDeviceConnector> clazz = getInterfaceClass(applicationConfiguration.getProperty(String.format("interfaces.%d.class",n)));
addInterface(clazz, applicationConfiguration.getProperty(String.format("interfaces.%d.settings",n)));
}
}
private void shutdown(){
log(INFO,"Application shutdown...");
/* Dispose all left frames */
for (Frame frame: JFrame.getFrames()){
frame.setVisible(false);
frame.dispose();
}
if (shouldSaveConfiguration){
applicationConfiguration.setProperty("interfaces.n", Integer.toString(interfaces.size()));
for (int n=0;n<interfaces.size();n++){
applicationConfiguration.setProperty(String.format("interfaces.%d.class", n), interfaces.get(n).getClass().getCanonicalName());
applicationConfiguration.setProperty(String.format("interfaces.%d.settings", n), interfaces.get(n).getConnectionSettings());
}
try {
log(INFO,"Save application configuration");
FileOutputStream fos = new FileOutputStream("synololog.cfg");
applicationConfiguration.storeToXML(fos, "Synololog Application Configuration");
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
log(ERROR,"synololog.cfg could not be created/opened for writing");
} catch (IOException e) {
log(ERROR,"synololog.cfg could not be written");
}
}
/*
this.scheduler.shutdown();
this.snapshotManager.doShutdown();
TaskletManager.instance().shutdown();
this.getServiceLink().close();
this.savePrefs();
*/
}
private void waitUiFinished(){
synchronized (uiSynchronization) {
while (!uiIsFinished){
try {
uiSynchronization.wait(250);
} catch (InterruptedException e){
log(e);
}
}
}
log(INFO,"UI notified finish");
}
public void notifyUiIsFinished(boolean saveApplicationConfiguration){
synchronized (uiSynchronization) {
uiIsFinished = true;
shouldSaveConfiguration = saveApplicationConfiguration;
uiSynchronization.notify();
}
}
/* Interface Types */
public List<Class<IDeviceConnector>> getInterfaceClasses(){
return this.interfaceClasses;
}
private Class<IDeviceConnector> getInterfaceClass(String className){
for (Class<IDeviceConnector> c:interfaceClasses){
if (c.getCanonicalName().equals(className))
return c;
}
return null;
}
/* Physical Interfaces */
public List<IDeviceConnector> getInterfaces(){
return this.interfaces;
}
public void addInterface(Class<IDeviceConnector> clazz,String connectionSettings){
try {
IDeviceConnector idc = clazz.newInstance();
idc.setConnectionSettings(connectionSettings);
interfaces.add(idc);
fireinterfacesChanged();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
public void removeInterface(IDeviceConnector intf){
interfaces.remove(intf);
fireinterfacesChanged();
}
private void fireinterfacesChanged(){
log(INFO,"interfaces changed");
for (PulsCounterApplicationListener l: applicationListeners){
l.interfacesChanged(this);
}
}
/* ToDO: Upgrade the old stuff ... */
/*
private void initialize(){
appSettingsListeners = new LinkedList<AppSettingsListener>();
exportSettings = new LinkedList<ExportSetting>();
scheduler = new Scheduler();
channelDescriptions = new String[32];
loadPrefs();
try {
snapshotManager = new SnapshotManager();
snapshotManager.notify(Notification.INITIALIZE);
} catch (FileNotFoundException e){
e.printStackTrace();
}
}
*/
public void addAppSettingsListener(AppSettingsListener listener){
appSettingsListeners.add(listener);
}
public void removeAppSettingsListener(AppSettingsListener listener){
appSettingsListeners.remove(listener);
}
public void addPulsCounterApplicationListener(PulsCounterApplicationListener listener){
applicationListeners.add(listener);
}
public void removePulsCounterApplicationListener(PulsCounterApplicationListener listener){
applicationListeners.remove(listener);
}
public void fireServiceLinkChanged(){
for (AppSettingsListener l: appSettingsListeners){
l.ServiceLinkChanged(serviceLink);
}
}
public void message(String message){
if (applicationListeners.size() == 0){
unseenMessages.addElement(message);
} else {
while (!unseenMessages.isEmpty()){
String msg = unseenMessages.remove(0);
for (PulsCounterApplicationListener listener: applicationListeners){
listener.messageArrived(msg);
}
}
for (PulsCounterApplicationListener listener: applicationListeners){
listener.messageArrived(message);
}
};
}
public synchronized NewSerialPort getSerialPort() {
if (serialPort == null){
serialPort = new NewSerialPort("COM1:");
}
return serialPort;
}
public synchronized void setSerialPort(NewSerialPort serialPort) {
if (serviceLink != null){
serviceLink.close();
serviceLink = null;
}
this.serialPort = serialPort;
getServiceLink();
fireServiceLinkChanged();
}
public synchronized ServiceLink getServiceLink() {
if (serviceLink == null){
serviceLink = new ServiceLink(getSerialPort());
serviceLink.getSerialPort().setTimeOut(200);
serviceLink.addServiceLinkListener(this);
}
return serviceLink;
}
public synchronized void setServiceLink(ServiceLink serviceLink) {
if (serviceLink != null){
serviceLink.close();
}
this.serviceLink = serviceLink;
fireServiceLinkChanged();
}
private Preferences getPreferencesNode(){
return Preferences.userNodeForPackage(getClass());
}
public void savePrefs(){
Preferences prefs = getPreferencesNode();
if (serialPort != null)
prefs.put("io.port", getSerialPort().getPortName());
System.out.println(String.format("savePrefs(): %d exportSettings werden gesichert.", exportSettings.size()));
if (exportSettings.size()>0)
{
for (int n=0;n<exportSettings.size();n++){
prefs.put(String.format("export.configuration.%d", n), ConfigurableObjects.getConfiguration(exportSettings.get(n)));
}
prefs.putInt("export.configurations", exportSettings.size());
};
Preferences nChannels = prefs.node("channels");
for (int n=0;n<32;n++){
nChannels.put(String.format("%d.description", n), channelDescriptions[n]);
}
try {
prefs.flush();
} catch (BackingStoreException e)
{
e.printStackTrace();
}
}
private void loadPrefs(){
Preferences prefs = getPreferencesNode();
String sn = prefs.get("io.port", null);
if (sn != null){
NewSerialPort nsp = new NewSerialPort(sn);
setSerialPort(nsp);
}
exportSettings.clear();
int nESC = prefs.getInt("export.configurations", 0);
for (int n=0;n<nESC;n++){
ExportSetting es = new ExportSetting();
ConfigurableObjects.setConfiguration(es, prefs.get(String.format("export.configuration.%d", n), ""));
exportSettings.add(es);
}
System.out.println(String.format("loadPrefs(): %d exportSettings geladen.", nESC));
Preferences nChannels = prefs.node("channels");
for (int n=0;n<32;n++){
channelDescriptions[n] = nChannels.get(String.format("%d.description", n), "");
}
}
public String getChannelDescription(int n){
return ""; // channelDescriptions[n];
}
public void setChannelDescription(int n,String desc){
channelDescriptions[n] = desc;
}
@Override
public void connectionStateChanged(Boolean connected) {
}
public SnapshotManager getSnapshotManager() {
return snapshotManager;
}
public List<ExportSetting> getExportSettings() {
return exportSettings;
}
}