All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.mvc.preferences.model.Preferences Maven / Gradle / Ivy

There is a newer version: 2.0.0-M1
Show newest version
package org.bidib.wizard.mvc.preferences.model;

import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.bidib.wizard.main.BiDiBWizard;
import org.bidib.wizard.mvc.common.model.PreferencesPortType;
import org.bidib.wizard.mvc.common.model.PreferencesPortType.ConnectionPortType;
import org.bidib.wizard.mvc.preferences.model.listener.PreferencesListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoodies.binding.beans.Model;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;

/**
 * The preferences of the Bidib-Wizard application.
 * 
 */
public final class Preferences extends Model {
    private static final long serialVersionUID = 1L;

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

    private static final String PREFERENCES_FILENAME = ".bidibwizardrc";

    // the default version of preferences
    private static final String DEFAULT_VERSION = "1.8-SNAPSHOT";

    private static final String PROPERTY_LABEL_PATH = "labelPath";

    private static final String PROPERTY_LOG_FILE_PATH = "logFilePath";

    @Deprecated
    private static final String PROPERTY_LOG_FILE = "logFile";

    @Deprecated
    private static final String PROPERTY_RXTX_LOG_FILE = "rxtxLogFile";

    private static final String PROPERTY_VERSION = "version";

    @Deprecated
    private static final String PROPERTY_MOCK = "mock";

    private static final String PROPERTY_SERIAL_ENABLED = "serialEnabled";

    private static final String PROPERTY_UDP_ENABLED = "udpEnabled";

    public static final String PROPERTY_SELECTED_PORTTYPE = "selectedPortType";

    private static final String PROPERTY_PREV_SELECTED_SERIAL_SYMLINK = "previousSelectedSerialSymLink";

    private static final String PROPERTY_PREV_SELECTED_COM_PORT = "previousSelectedComPort";

    private static final String PROPERTY_PREV_SELECTED_UDP_HOST = "previousSelectedUdpHost";

    private static final String PROPERTY_START_TIME = "startTime";

    private static final String PROPERTY_TIME_FACTOR = "timeFactor";

    private static final String PROPERTY_WORKING_DIRECTORY = "workingDirectory";

    private static final String PROPERTY_DMX_MAPPING_OFFSET = "dmxMappingOffset";

    private static final String PROPERTY_RESET_RECONNECT_DELAY = "resetReconnectDelay";

    private static final String PROPERTY_IGNORE_WAIT_TIMEOUT = "ignoreWaitTimeout";

    private static final String PROPERTY_RESPONSE_TIMEOUT = "responseTimeout";

    private static final String PROPERTY_POWER_USER = "powerUser";

    private static final String PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH = "ptModeDoNotConfirmSwitch";

    private static final String PROPERTY_SHOW_BOOSTER_TABLE = "showBoosterTable";

    public static final String PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE = "alwaysShowProductNameInTree";

    public static final String PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER = "ignoreWrongReceiveMessageNumber";

    private static final String PROPERTY_IGNORE_FLOW_CONTROL = "ignoreFlowControl";

    private static final String PROPERTY_FIRMWARE_PACKET_TIMEOUT = "firmwarePacketTimeout";

    private static final String PROPERTY_WINDOW_POSITION = "windowPosition";

    @Deprecated
    public static final String PROPERTY_SELECTED_DEBUG_PORTTYPE = "selectedDebugPortType";

    @Deprecated
    public static final String PROPERTY_PREV_SELECTED_DEBUG_PORT = "previousSelectedDebugPort";

    @Deprecated
    public static final String PROPERTY_DEBUG_BAUD_RATE = "debugBaudRate";

    public static final String PROPERTY_RAILCOM_PLUS_VENDOR_IDS = "railcomPlusVendorIds";

    private static final int DEFAULT_FIRMWARE_PACKET_TIMEOUT = 4500;

    public static final String PROPERTY_POM_UPDATE_INITIAL_DELAY = "pomUpdateInitialDelay";

    private static final int DEFAULT_POM_UPDATE_INITIAL_DELAY = 1000;

    public static final String PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS = "pomUpdateDelayBetweenPackets";

    private static final int DEFAULT_POM_UPDATE_DELAY_BETWEEN_PACKETS = 0;

    public static final String PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT = "pomUpdateResendPacketCount";

    private static final int DEFAULT_POM_UPDATE_RESEND_PACKET_COUNT = 0;

    public static final String PROPERTY_SERIAL_PORT_PROVIDER = "serialPortProvider";

    private static Preferences instance = null;

    private static String preferencesPath = null;

    private final Collection listeners = new LinkedList();

    private final SimpleDateFormat format = new SimpleDateFormat("HH:mm");

    private Properties properties;

    private String preferencesVersion;

    private boolean reloadLogConfigurationPending;

    private Preferences() {
        properties = new Properties();
    }

    private void load() {
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(new File(preferencesPath, PREFERENCES_FILENAME));
            properties.load(fis);
        }
        catch (FileNotFoundException e) {
            // create initial properties
            throw new IllegalArgumentException("No preferences found at: " + preferencesPath + "/"
                + PREFERENCES_FILENAME, e);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            if (fis != null) {
                try {
                    fis.close();
                }
                catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static synchronized Preferences getInstance() {
        if (instance == null) {
            Preferences tempInstance = new Preferences();
            try {
                // try to load the properties from the file
                tempInstance.load();
                tempInstance.checkVersionUpgrade();

                // no problem detected
                instance = tempInstance;
            }
            catch (IllegalArgumentException ex) {
                // the file is not available, create new file with default values
                tempInstance.loadDefaultValues();
                tempInstance.save(tempInstance.createPreferencesModel());
                instance = tempInstance;
            }
        }
        return instance;
    }

    private void checkVersionUpgrade() {
        boolean changes = false;
        boolean mustUpgrade = false;
        // check the version and update if necessary
        String[] version = getVersion();
        String[] currentVersion = DEFAULT_VERSION.split("\\.");
        if (!currentVersion[0].equals(version[0])) {
            LOGGER.info("The major version has changed!");
            mustUpgrade = true;
        }
        else if (!currentVersion[1].equals(version[1])) {
            LOGGER.info("The minor version has changed!");
            mustUpgrade = true;
        }
        else if (currentVersion[1].endsWith("-SNAPSHOT")) {
            LOGGER.info("Upgrade is forced because the current version is a SNAPSHOT version!");
            mustUpgrade = true;
        }

        if (mustUpgrade) {
            // check all properties
            String logFilePath = getLogFilePath();
            File dir = new File(logFilePath);
            if (dir.exists()) {
                LOGGER.debug("Change the logfile to logfilepath: {}", logFilePath);
                setLogFilePath(logFilePath);
            }

            if (properties.containsKey(PROPERTY_LOG_FILE)) {
                // remove the RXTX path
                properties.remove(PROPERTY_RXTX_LOG_FILE);
                properties.remove(PROPERTY_LOG_FILE);
            }

            properties.remove(PROPERTY_DMX_MAPPING_OFFSET);
            // if (!properties.containsKey(PROPERTY_DMX_MAPPING_OFFSET)) {
            // properties.put(PROPERTY_DMX_MAPPING_OFFSET, "1");
            // }

            if (!properties.containsKey(PROPERTY_RESET_RECONNECT_DELAY)) {
                properties.put(PROPERTY_RESET_RECONNECT_DELAY, "1500");
            }

            if (!properties.containsKey(PROPERTY_IGNORE_WAIT_TIMEOUT)) {
                properties.put(PROPERTY_IGNORE_WAIT_TIMEOUT, "false");
            }
            else if (preferencesVersion.startsWith("1.5")) {
                properties.put(PROPERTY_IGNORE_WAIT_TIMEOUT, "false");
            }

            if (!properties.containsKey(PROPERTY_RESPONSE_TIMEOUT)) {
                properties.put(PROPERTY_RESPONSE_TIMEOUT, "200");
            }

            if (!properties.containsKey(PROPERTY_POWER_USER)) {
                properties.put(PROPERTY_POWER_USER, "false");
            }

            if (!properties.containsKey(PROPERTY_SERIAL_ENABLED)) {
                properties.put(PROPERTY_SERIAL_ENABLED, "true");
            }

            if (!properties.containsKey(PROPERTY_UDP_ENABLED)) {
                properties.put(PROPERTY_UDP_ENABLED, "true");
            }

            if (!properties.containsKey(PROPERTY_SELECTED_PORTTYPE)) {
                properties.put(PROPERTY_SELECTED_PORTTYPE, ConnectionPortType.SerialPort.toString());
            }

            if (properties.containsKey(PROPERTY_SELECTED_DEBUG_PORTTYPE)) {
                // remove the property
                properties.remove(PROPERTY_SELECTED_DEBUG_PORTTYPE);
            }

            if (properties.containsKey(PROPERTY_PREV_SELECTED_DEBUG_PORT)) {
                // remove the property
                properties.remove(PROPERTY_PREV_SELECTED_DEBUG_PORT);
            }

            if (properties.containsKey(PROPERTY_DEBUG_BAUD_RATE)) {
                // remove the property
                properties.remove(PROPERTY_DEBUG_BAUD_RATE);
            }

            if (properties.containsKey(PROPERTY_MOCK)) {
                // remove the mock property
                properties.remove(PROPERTY_MOCK);
            }
            if (properties.containsKey("commPort")) {
                // remove the commPort property
                properties.remove("commPort");
            }

            if (!properties.containsKey(PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH)) {
                properties.put(PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH, "false");
            }

            if (!properties.containsKey(PROPERTY_SHOW_BOOSTER_TABLE)) {
                properties.put(PROPERTY_SHOW_BOOSTER_TABLE, "true");
            }

            if (!properties.containsKey(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE)) {
                properties.put(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE, "false");
            }

            if (!properties.containsKey(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER)) {
                properties.put(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER, "false");
            }

            if (!properties.containsKey(PROPERTY_IGNORE_FLOW_CONTROL)) {
                properties.put(PROPERTY_IGNORE_FLOW_CONTROL, "false");
            }

            if (!properties.containsKey(PROPERTY_FIRMWARE_PACKET_TIMEOUT)) {
                properties.put(PROPERTY_FIRMWARE_PACKET_TIMEOUT, Integer.toString(DEFAULT_FIRMWARE_PACKET_TIMEOUT));
            }
            if (properties.containsKey("firmwarePaketTimeout")) {
                // remove the firmwarePaketTimeout property
                properties.remove("firmwarePaketTimeout");
            }

            if (!properties.containsKey(PROPERTY_POM_UPDATE_INITIAL_DELAY)) {
                properties.put(PROPERTY_POM_UPDATE_INITIAL_DELAY, Integer.toString(DEFAULT_POM_UPDATE_INITIAL_DELAY));
            }
            if (!properties.containsKey(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS)) {
                properties.put(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS,
                    Integer.toString(DEFAULT_POM_UPDATE_DELAY_BETWEEN_PACKETS));
            }
            if (!properties.containsKey(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT)) {
                properties.put(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT,
                    Integer.toString(DEFAULT_POM_UPDATE_RESEND_PACKET_COUNT));
            }

            changes = true;
        }

        // save if necessary
        if (changes) {
            properties.put(PROPERTY_VERSION, DEFAULT_VERSION);
            save(null);
        }
    }

    private void loadDefaultValues() {
        getLogFilePath();
    }

    public void addPreferencesListener(PreferencesListener l) {
        listeners.add(l);
    }

    /**
     * Create a new PreferencesModel based on the current values of Preferences.
     * 
     * @return the new PreferencesModel instance
     */
    public PreferencesModel createPreferencesModel() {
        PreferencesModel preferencesModel = new PreferencesModel();
        preferencesModel.setSerialEnabled(isSerialEnabled());
        preferencesModel.setUdpEnabled(isUdpEnabled());
        preferencesModel.setSelectedPortType(getSelectedPortType());
        preferencesModel.setPreviousSelectedSerialSymLink(getPreviousSelectedSerialSymLink());
        preferencesModel.setPreviousSelectedComPort(getPreviousSelectedComPort());
        preferencesModel.setPreviousSelectedUdpHost(getPreviousSelectedUdpHost());
        preferencesModel.setStartTime(getStartTime());
        preferencesModel.setTimeFactor(getTimeFactor());
        preferencesModel.setLogFilePath(getLogFilePath());
        preferencesModel.setLabelPath(getLabelPath());
        preferencesModel.setPowerUser(isPowerUser());
        preferencesModel.setShowBoosterTable(isShowBoosterTable());
        preferencesModel.setAlwaysShowProductNameInTree(isAlwaysShowProductNameInTree());
        preferencesModel.setIgnoreWrongReceiveMessageNumber(isIgnoreWrongReceiveMessageNumber());
        preferencesModel.setIgnoreWaitTimeout(isIgnoreWaitTimeout());
        preferencesModel.setIgnoreFlowControl(isIgnoreFlowControl());
        preferencesModel.setFirmwarePacketTimeout(getFirmwarePacketTimeout());

        preferencesModel.setEncodedWindowPosition(getWindowPosition());

        preferencesModel.setRailcomPlusVendorIds(getRailcomPlusVendorIds());

        preferencesModel.setPomUpdateInitialDelay(getPomUpdateInitialDelay());
        preferencesModel.setPomUpdateDelayBetweenPackets(getPomUpdateDelayBetweenPackets());
        preferencesModel.setPomUpdateResendPacketCount(getPomUpdateResendPacketCount());

        LOGGER.debug("Created new references model: {}", preferencesModel);
        return preferencesModel;
    }

    private String[] getVersion() {
        String[] parts = null;
        try {
            // the version property was added with 1.4, if none is available use 1.3 as version
            // to make sure the preferences are migrated
            preferencesVersion = properties.getProperty(PROPERTY_VERSION, "1.3");
            LOGGER.debug("Get the stored version: {}", preferencesVersion);
            parts = preferencesVersion.split("\\.");
        }
        catch (Exception ex) {
            // use a preferences version that causes the migration
            preferencesVersion = "1.3";
            parts = preferencesVersion.split("\\.");
        }
        return parts;
    }

    public String getLabelPath() {
        String result = properties.getProperty(PROPERTY_LABEL_PATH);

        if (result == null || result.isEmpty()) {
            result = new File(preferencesPath, "." + BiDiBWizard.class.getSimpleName()).getPath();
        }
        return result;
    }

    public String getLogFilePath() {
        String logFilePath = properties.getProperty(PROPERTY_LOG_FILE_PATH);

        if (logFilePath == null || logFilePath.isEmpty()) {
            logFilePath = new File(System.getProperty("java.io.tmpdir")).getPath();

            // set in properties to be saved later
            properties.setProperty(PROPERTY_LOG_FILE_PATH, logFilePath);
        }
        return logFilePath;
    }

    public Date getStartTime() {
        try {
            return format.parse(properties.getProperty(PROPERTY_START_TIME, "06:00"));
        }
        catch (ParseException ex) {
            LOGGER.warn("Parse the start time failed.", ex);
        }
        return new Date();
    }

    public int getTimeFactor() {
        return Integer.parseInt(properties.getProperty(PROPERTY_TIME_FACTOR, "1"));
    }

    public int getFirmwarePacketTimeout() {
        return Integer.parseInt(properties.getProperty(PROPERTY_FIRMWARE_PACKET_TIMEOUT,
            Integer.toString(DEFAULT_FIRMWARE_PACKET_TIMEOUT)));
    }

    public String getWorkingDirectory() {
        return properties.getProperty(PROPERTY_WORKING_DIRECTORY);
    }

    public boolean isSerialEnabled() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_SERIAL_ENABLED, "true"));
    }

    public boolean isUdpEnabled() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_UDP_ENABLED, "false"));
    }

    public PreferencesPortType getSelectedPortType() {
        // default port type is serial port
        String value = properties.getProperty(PROPERTY_SELECTED_PORTTYPE, ConnectionPortType.SerialPort.name());
        PreferencesPortType preferencesPortType = PreferencesPortType.getValue(value);

        LOGGER.debug("Get the selected port type from preferences: {}", preferencesPortType);
        return preferencesPortType;
    }

    public String getRailcomPlusVendorIds() {
        String vendorIds = properties.getProperty(PROPERTY_RAILCOM_PLUS_VENDOR_IDS);
        LOGGER.debug("Get the railcom plus vendor Ids: {}", vendorIds);

        return vendorIds;
    }

    public String getPreviousSelectedSerialSymLink() {
        return properties.getProperty(PROPERTY_PREV_SELECTED_SERIAL_SYMLINK);
    }

    public String getPreviousSelectedComPort() {
        return properties.getProperty(PROPERTY_PREV_SELECTED_COM_PORT);
    }

    public String getPreviousSelectedUdpHost() {
        return properties.getProperty(PROPERTY_PREV_SELECTED_UDP_HOST);
    }

    public int getResetReconnectDelay() {
        return Integer.parseInt(properties.getProperty(PROPERTY_RESET_RECONNECT_DELAY, "1500"));
    }

    public boolean isIgnoreWaitTimeout() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_IGNORE_WAIT_TIMEOUT, "true"));
    }

    public int getResponseTimeout() {
        return Integer.parseInt(properties.getProperty(PROPERTY_RESPONSE_TIMEOUT, "200"));
    }

    public boolean isPowerUser() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_POWER_USER, "false"));
    }

    public boolean isPtModeDoNotConfirmSwitch() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH, "false"));
    }

    public boolean isShowBoosterTable() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_SHOW_BOOSTER_TABLE, "true"));
    }

    public boolean isAlwaysShowProductNameInTree() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE, "false"));
    }

    public boolean isIgnoreWrongReceiveMessageNumber() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER, "false"));
    }

    public boolean isIgnoreFlowControl() {
        return Boolean.valueOf(properties.getProperty(PROPERTY_IGNORE_FLOW_CONTROL, "false"));
    }

    public String getWindowPosition() {
        return properties.getProperty(PROPERTY_WINDOW_POSITION);
    }

    public void setPomUpdateInitialDelay(int pomUpdateInitialDelay) {
        int oldValue = getIntegerProperty(PROPERTY_POM_UPDATE_INITIAL_DELAY, DEFAULT_POM_UPDATE_INITIAL_DELAY);
        properties.setProperty(PROPERTY_POM_UPDATE_INITIAL_DELAY, String.valueOf(pomUpdateInitialDelay));

        firePropertyChange(PROPERTY_POM_UPDATE_INITIAL_DELAY, oldValue, pomUpdateInitialDelay);
    }

    public int getPomUpdateInitialDelay() {
        return getIntegerProperty(PROPERTY_POM_UPDATE_INITIAL_DELAY, DEFAULT_POM_UPDATE_INITIAL_DELAY);
    }

    public String getSerialPortProvider() {
        return properties.getProperty(PROPERTY_SERIAL_PORT_PROVIDER, "RXTX");
    }

    public void setPomUpdateDelayBetweenPackets(int pomUpdateDelayBetweenPackets) {
        int oldValue =
            getIntegerProperty(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS, DEFAULT_POM_UPDATE_DELAY_BETWEEN_PACKETS);
        properties.setProperty(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS, String.valueOf(pomUpdateDelayBetweenPackets));

        firePropertyChange(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS, oldValue, pomUpdateDelayBetweenPackets);
    }

    public int getPomUpdateDelayBetweenPackets() {
        return getIntegerProperty(PROPERTY_POM_UPDATE_DELAY_BETWEEN_PACKETS, DEFAULT_POM_UPDATE_DELAY_BETWEEN_PACKETS);
    }

    public void setPomUpdateResendPacketCount(int pomUpdateResendPacketCount) {
        int oldValue =
            getIntegerProperty(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT, DEFAULT_POM_UPDATE_RESEND_PACKET_COUNT);
        properties.setProperty(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT, String.valueOf(pomUpdateResendPacketCount));

        firePropertyChange(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT, oldValue, pomUpdateResendPacketCount);
    }

    public int getPomUpdateResendPacketCount() {
        return getIntegerProperty(PROPERTY_POM_UPDATE_RESEND_PACKET_COUNT, DEFAULT_POM_UPDATE_RESEND_PACKET_COUNT);
    }

    /**
     * Save the preference values provided by the preferences model if available.
     * 
     * @param preferencesModel
     *            the preferences model to save
     */
    public void save(PreferencesModel preferencesModel) {

        if (preferencesModel != null) {
            // save the provided preferences model

            setTimeFactor(preferencesModel.getTimeFactor());
            setStartTime(preferencesModel.getStartTime());
            setLogFilePath(preferencesModel.getLogFilePath());
            setLabelPath(preferencesModel.getLabelPath());
            setPowerUser(preferencesModel.isPowerUser());
            setShowBoosterTable(preferencesModel.isShowBoosterTable());
            setAlwaysShowProductNameInTree(preferencesModel.isAlwaysShowProductNameInTree());
            setIgnoreWaitTimeout(preferencesModel.isIgnoreWaitTimeout());
            setIgnoreWrongReceiveMessageNumber(preferencesModel.isIgnoreWrongReceiveMessageNumber());
            setIgnoreFlowControl(preferencesModel.isIgnoreFlowControl());

            setFirmwarePacketTimeout(preferencesModel.getFirmwarePacketTimeout());

            // set mock before comm port because the later triggers reload ports
            setSerialEnabled(preferencesModel.isSerialEnabled());
            setUdpEnabled(preferencesModel.isUdpEnabled());
            setPreviousSelectedSerialSymLink(preferencesModel.getPreviousSelectedSerialSymLink());
            setPreviousSelectedComPort(preferencesModel.getPreviousSelectedComPort());
            setPreviousSelectedUdpHost(preferencesModel.getPreviousSelectedUdpHost());

            setWindowPosition(preferencesModel.getEncodedWindowPosition());

            setRailcomPlusVendorIds(preferencesModel.getRailcomPlusVendorIds());

            setPomUpdateInitialDelay(preferencesModel.getPomUpdateInitialDelay());
            setPomUpdateDelayBetweenPackets(preferencesModel.getPomUpdateDelayBetweenPackets());
            setPomUpdateResendPacketCount(preferencesModel.getPomUpdateResendPacketCount());

            // set the selected port type
            // reconnect is triggered
            setSelectedPortType(preferencesModel.getSelectedPortType());
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(new File(preferencesPath, PREFERENCES_FILENAME));
            properties.store(fos, "user properties for " + BiDiBWizard.class.getSimpleName() + " configuration");
        }
        catch (IOException e) {
            LOGGER.warn("Store properties failed.", e);
        }
        finally {
            if (fos != null) {
                try {
                    fos.flush(); // flush the stream
                    fos.close();
                }
                catch (IOException e) {
                    LOGGER.warn("Flush or close file stream failed.", e);
                }
            }
        }
    }

    /**
     * Reload the logger configuration to make sure the changed settings for logfile location are applied. Make sure the
     * Preferences are saved before calling this method.
     * 
     * @param force
     *            force reload
     */
    public void reloadLoggerConfiguration(boolean force) {

        if (!force && !isReloadLogConfigurationPending()) {
            LOGGER.debug("Reload log configuration is skipped.");
            return;
        }
        // assume SLF4J is bound to logback in the current environment
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();

        try {
            JoranConfigurator configurator = new JoranConfigurator();
            configurator.setContext(context);
            // Call context.reset() to clear any previous configuration, e.g. default
            // configuration. For multi-step configuration, omit calling context.reset().
            context.reset();

            File logbackFile = new File(preferencesPath, "logback.xml");
            if (!logbackFile.exists()) {
                // fallback to installation directory
                logbackFile = new File("logback.xml");
            }
            LOGGER.info("logbackFile: {}", logbackFile.getAbsolutePath());
            InputStream logbackConfig = null;
            if (logbackFile.exists()) {
                try {
                    logbackConfig = new BufferedInputStream(new FileInputStream(logbackFile));
                }
                catch (FileNotFoundException ex) {
                    LOGGER.warn("Load user-defined logback configuration failed.", ex);
                }
            }
            if (logbackConfig == null) {
                LOGGER.info("Use default logback config.");
                logbackConfig = BiDiBWizard.class.getResourceAsStream("/config/logback-default.xml");
            }
            else {
                LOGGER.info("Using user-defined logback config.");
            }
            configurator.doConfigure(logbackConfig);
        }
        catch (JoranException je) {
            // StatusPrinter will handle this
        }

        StatusPrinter.printInCaseOfErrorsOrWarnings(context);
    }

    public void setSelectedPortType(PreferencesPortType portType) {
        Object oldValue = getSelectedPortType();
        LOGGER.info("Set the new selected port type: {}, old value: {}", portType, oldValue);

        properties.setProperty(PROPERTY_SELECTED_PORTTYPE, (portType != null ? portType.toString() : ""));
        firePropertyChange(PROPERTY_SELECTED_PORTTYPE, oldValue, portType);
    }

    public void setRailcomPlusVendorIds(String vendorIds) {
        String oldValue = getRailcomPlusVendorIds();

        LOGGER.info("Set the new railcom plus vendor ids: {}, old value: {}", vendorIds, oldValue);

        properties.setProperty(PROPERTY_RAILCOM_PLUS_VENDOR_IDS, (vendorIds != null ? vendorIds : ""));
        firePropertyChange(PROPERTY_RAILCOM_PLUS_VENDOR_IDS, oldValue, vendorIds);
    }

    public void setPreviousSelectedSerialSymLink(String prevSelectedSerialSymLink) {
        LOGGER.debug("Set the previous selected serial symLink: {}", prevSelectedSerialSymLink);
        if (prevSelectedSerialSymLink == null) {
            prevSelectedSerialSymLink = "";
        }
        properties.setProperty(PROPERTY_PREV_SELECTED_SERIAL_SYMLINK, prevSelectedSerialSymLink);
        firePrevSelectedSerialSymLinkChanged(prevSelectedSerialSymLink);
    }

    public void setPreviousSelectedComPort(String prevSelectedComPort) {
        LOGGER.debug("Set the previous selected COM port: {}", prevSelectedComPort);
        if (prevSelectedComPort == null) {
            prevSelectedComPort = "";
        }
        properties.setProperty(PROPERTY_PREV_SELECTED_COM_PORT, prevSelectedComPort);
        firePrevSelectedComPortChanged(prevSelectedComPort);
    }

    public void setPreviousSelectedUdpHost(String prevSelectedUdpHost) {
        LOGGER.debug("Set the previous selected udp host: {}", prevSelectedUdpHost);
        if (prevSelectedUdpHost == null) {
            prevSelectedUdpHost = "";
        }
        properties.setProperty(PROPERTY_PREV_SELECTED_UDP_HOST, prevSelectedUdpHost);
        firePrevSelectedUdpHostChanged(prevSelectedUdpHost);
    }

    public static void setPath(String path) {
        preferencesPath = path;
    }

    public void setLabelPath(String labelPath) {
        properties.setProperty(PROPERTY_LABEL_PATH, labelPath);
    }

    /**
     * Set the path to the location where the log files are written
     * 
     * @param logFilePath
     *            the path to the log files
     */
    public void setLogFilePath(String logFilePath) {
        String oldLogFilePath = properties.getProperty(PROPERTY_LOG_FILE_PATH);
        LOGGER.debug("Set the new logfile path: {}, oldLogFilePath: {}", logFilePath, oldLogFilePath);

        properties.setProperty(PROPERTY_LOG_FILE_PATH, logFilePath);

        if (logFilePath != null && !logFilePath.equalsIgnoreCase(oldLogFilePath)) {
            // the logfile has changed -> set the reload log configuration pending flag
            LOGGER.debug("The log configuration has changed.");
            reloadLogConfigurationPending = true;
        }
    }

    public void setSerialEnabled(boolean serialEnabled) {
        Boolean oldValue = getBooleanProperty(PROPERTY_SERIAL_ENABLED);
        properties.setProperty(PROPERTY_SERIAL_ENABLED, Boolean.valueOf(serialEnabled).toString());
        if (oldValue == null || oldValue.booleanValue() != serialEnabled) {
            LOGGER.debug("SerialEnabled has changed.");
            fireSerialEnabledChanged(serialEnabled);
        }
    }

    public void setUdpEnabled(boolean udpEnabled) {
        Boolean oldValue = getBooleanProperty(PROPERTY_UDP_ENABLED);
        properties.setProperty(PROPERTY_UDP_ENABLED, Boolean.valueOf(udpEnabled).toString());
        if (oldValue == null || oldValue.booleanValue() != udpEnabled) {
            LOGGER.debug("UdpEnabled has changed.");
            fireUdpEnabledChanged(udpEnabled);
        }
    }

    private Boolean getBooleanProperty(String key) {
        Object prop = properties.getProperty(key);
        Boolean value = null;
        if (prop != null) {
            value = Boolean.valueOf(prop.toString());
        }
        return value;
    }

    private int getIntegerProperty(String key, int defaultValue) {
        Object prop = properties.getProperty(key);
        int value = defaultValue;
        if (prop != null) {
            try {
                value = Integer.valueOf(prop.toString());
            }
            catch (Exception ex) {
                LOGGER.warn("Get property value as int failed, return default value: {}", defaultValue, ex);
                value = defaultValue;
            }
        }
        else {
            LOGGER.info("The property value is not available, return default value: {}", defaultValue);
        }
        return value;
    }

    public void setStartTime(Date startTime) {
        properties.setProperty(PROPERTY_START_TIME, format.format(startTime));
        fireStartTimeChanged(startTime);
    }

    public void setTimeFactor(int timeFactor) {
        properties.setProperty(PROPERTY_TIME_FACTOR, String.valueOf(timeFactor));
        fireTimeFactorChanged(timeFactor);
    }

    public void setWorkingDirectory(String workingDirectory) {
        properties.setProperty(PROPERTY_WORKING_DIRECTORY, workingDirectory);
    }

    // public void setDmxMappingOffset(int dmxMappingOffset) {
    // properties.setProperty(PROPERTY_DMX_MAPPING_OFFSET, String.valueOf(dmxMappingOffset));
    // fireDmxMappingOffsetChanged(dmxMappingOffset);
    // }

    public void setResetReconnectDelay(int resetReconnectDelay) {
        properties.setProperty(PROPERTY_RESET_RECONNECT_DELAY, String.valueOf(resetReconnectDelay));
        fireResetReconnectDelayChanged(resetReconnectDelay);
    }

    public void setIgnoreWaitTimeout(boolean ignoreWaitTimeout) {
        Boolean oldValue = getBooleanProperty(PROPERTY_IGNORE_WAIT_TIMEOUT);
        properties.setProperty(PROPERTY_IGNORE_WAIT_TIMEOUT, Boolean.valueOf(ignoreWaitTimeout).toString());
        // if (oldValue == null || oldValue.booleanValue() != ignoreWaitTimeout) {
        LOGGER.debug("IgnoreWaitTimeout has changed.");
        fireIgnoreWaitTimeoutChanged(oldValue, ignoreWaitTimeout);
        // }
    }

    public void setResponseTimeout(int responseTimeout) {
        properties.setProperty(PROPERTY_RESPONSE_TIMEOUT, String.valueOf(responseTimeout));
        fireResponseTimeoutChanged(responseTimeout);
    }

    public void setFirmwarePacketTimeout(int firmwarePacketTimeout) {
        int oldValue = getIntegerProperty(PROPERTY_FIRMWARE_PACKET_TIMEOUT, DEFAULT_FIRMWARE_PACKET_TIMEOUT);
        properties.setProperty(PROPERTY_FIRMWARE_PACKET_TIMEOUT, String.valueOf(firmwarePacketTimeout));
        fireFirmwarePacketTimeoutChanged(oldValue, firmwarePacketTimeout);
    }

    public void setPowerUser(boolean powerUser) {
        Boolean oldValue = getBooleanProperty(PROPERTY_POWER_USER);
        properties.setProperty(PROPERTY_POWER_USER, Boolean.valueOf(powerUser).toString());
        if (oldValue == null || oldValue.booleanValue() != powerUser) {
            LOGGER.debug("PowerUser has changed.");
            firePowerUserChanged(powerUser);
        }
    }

    public void setPtModeDoNotConfirmSwitch(boolean ptModeDoNotConfirmSwitch) {
        Boolean oldValue = getBooleanProperty(PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH);
        properties.setProperty(PROPERTY_PT_MODE_DO_NOT_CONFIRM_SWITCH, Boolean
            .valueOf(ptModeDoNotConfirmSwitch).toString());
        if (oldValue == null || oldValue.booleanValue() != ptModeDoNotConfirmSwitch) {
            LOGGER.debug("PtModeDoNotConfirmSwitch has changed.");
            firePtModeDoNotConfirmSwitchChanged(ptModeDoNotConfirmSwitch);
        }
    }

    public void setShowBoosterTable(boolean showBoosterTable) {
        Boolean oldValue = getBooleanProperty(PROPERTY_SHOW_BOOSTER_TABLE);
        properties.setProperty(PROPERTY_SHOW_BOOSTER_TABLE, Boolean.valueOf(showBoosterTable).toString());
        if (oldValue == null || oldValue.booleanValue() != showBoosterTable) {
            LOGGER.debug("ShowBoosterTable has changed.");
            fireShowBoosterTableChanged(oldValue, showBoosterTable);
        }
    }

    public void setAlwaysShowProductNameInTree(boolean alwaysShowProductNameInTree) {
        Boolean oldValue = getBooleanProperty(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE);
        properties.setProperty(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE, Boolean
            .valueOf(alwaysShowProductNameInTree).toString());

        fireAlwaysShowProductNameInTreeChanged(oldValue, alwaysShowProductNameInTree);
    }

    public void setIgnoreWrongReceiveMessageNumber(boolean ignoreWrongReceiveMessageNumber) {
        Boolean oldValue = getBooleanProperty(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER);
        properties.setProperty(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER,
            Boolean.valueOf(ignoreWrongReceiveMessageNumber).toString());

        fireIgnoreWrongReceiveMessageNumber(oldValue, ignoreWrongReceiveMessageNumber);
    }

    public void setIgnoreFlowControl(boolean ignoreFlowControl) {
        Boolean oldValue = getBooleanProperty(PROPERTY_IGNORE_FLOW_CONTROL);
        properties.setProperty(PROPERTY_IGNORE_FLOW_CONTROL, Boolean.valueOf(ignoreFlowControl).toString());

        fireIgnoreFlowControl(oldValue, ignoreFlowControl);
    }

    public void setWindowPosition(String windowPosition) {
        LOGGER.debug("Set the window position: {}", windowPosition);
        if (StringUtils.isNotBlank(windowPosition)) {
            properties.setProperty(PROPERTY_WINDOW_POSITION, windowPosition);
        }
        else {
            properties.remove(PROPERTY_WINDOW_POSITION);
        }
    }

    private void firePrevSelectedSerialSymLinkChanged(String prevSelectedSerialSymLink) {
        for (PreferencesListener l : listeners) {
            LOGGER.debug("Notify listener that the previous selected serial symlink has changed: {}", l);
            l.prevSelectedSerialSymLinkChanged(prevSelectedSerialSymLink);
        }
    }

    private void firePrevSelectedComPortChanged(String prevSelectedComPort) {
        for (PreferencesListener l : listeners) {
            LOGGER.debug("Notify listener that the previous selected COM port has changed: {}", l);
            l.prevSelectedComPortChanged(prevSelectedComPort);
        }
    }

    private void firePrevSelectedUdpHostChanged(String prevSelectedUdpHost) {
        for (PreferencesListener l : listeners) {
            LOGGER.debug("Notify listener that the previous selected udp host has changed: {}", l);
            l.prevSelectedUdpHostChanged(prevSelectedUdpHost);
        }
    }

    private void fireSerialEnabledChanged(boolean serialEnabled) {
        for (PreferencesListener l : listeners) {
            l.serialEnabledChanged(serialEnabled);
        }
    }

    private void fireUdpEnabledChanged(boolean udpEnabled) {
        for (PreferencesListener l : listeners) {
            l.udpEnabledChanged(udpEnabled);
        }
    }

    private void fireStartTimeChanged(Date startTime) {
        for (PreferencesListener l : listeners) {
            l.startTimeChanged(startTime);
        }
    }

    private void fireTimeFactorChanged(int timeFactor) {
        for (PreferencesListener l : listeners) {
            l.timeFactorChanged(timeFactor);
        }
    }

    private void fireResetReconnectDelayChanged(int resetReconnectDelay) {
        for (PreferencesListener l : listeners) {
            l.resetReconnectDelayChanged(resetReconnectDelay);
        }
    }

    private void fireIgnoreWaitTimeoutChanged(Boolean oldValue, Boolean newValue) {
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_IGNORE_WAIT_TIMEOUT, oldValue, newValue);
        }
    }

    private void fireResponseTimeoutChanged(int responseTimeout) {
        for (PreferencesListener l : listeners) {
            l.responseTimeoutChanged(responseTimeout);
        }
    }

    private void fireFirmwarePacketTimeoutChanged(int oldValue, int firmwarePacketTimeout) {
        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_FIRMWARE_PACKET_TIMEOUT, oldValue, firmwarePacketTimeout);
        }
    }

    private void firePowerUserChanged(boolean powerUser) {
        for (PreferencesListener l : listeners) {
            l.powerUserChanged(powerUser);
        }
    }

    private void fireShowBoosterTableChanged(Boolean oldValue, Boolean newValue) {
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_SHOW_BOOSTER_TABLE, oldValue, newValue);
        }
    }

    private void fireAlwaysShowProductNameInTreeChanged(Boolean oldValue, Boolean newValue) {
        LOGGER.info("The AlwaysShowProductNameInTreeChanged has changed, oldValue: {}, newValue: {}", oldValue,
            newValue);

        if (Objects.equals(oldValue, newValue)) {
            return;
        }

        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_ALWAYS_SHOW_PRODUCTNAME_IN_TREE, oldValue, newValue);
        }
    }

    private void firePtModeDoNotConfirmSwitchChanged(boolean ptModeDoNotConfirmSwitch) {
        for (PreferencesListener l : listeners) {
            l.ptModeDoNotConfirmSwitchChanged(ptModeDoNotConfirmSwitch);
        }
    }

    private void fireIgnoreWrongReceiveMessageNumber(Boolean oldValue, Boolean newValue) {
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_IGNORE_WRONG_RECEIVE_MESSAGE_NUMBER, oldValue, newValue);
        }
    }

    private void fireIgnoreFlowControl(Boolean oldValue, Boolean newValue) {
        if (Objects.equals(oldValue, newValue)) {
            return;
        }
        for (PreferencesListener l : listeners) {
            l.propertyChanged(PROPERTY_IGNORE_FLOW_CONTROL, oldValue, newValue);
        }
    }

    /**
     * @return the reloadLogConfigurationPending
     */
    public boolean isReloadLogConfigurationPending() {
        return reloadLogConfigurationPending;
    }

    /**
     * @param reloadLogConfigurationPending
     *            the reloadLogConfigurationPending to set
     */
    public void setReloadLogConfigurationPending(boolean reloadLogConfigurationPending) {
        this.reloadLogConfigurationPending = reloadLogConfigurationPending;
    }

    public void printPreferences() {
        LOGGER.info("Current java version: {}, os: {} - {}-bit, user: {}", System.getProperty("java.version"),
            System.getProperty("os.name"), System.getProperty("sun.arch.data.model"), System.getProperty("user.name"));
        LOGGER.info("Current preferences: {}", properties);

        Properties version = new Properties();
        try {
            version.load(getClass().getResourceAsStream("/build.properties"));
            LOGGER.info("Current version: {}", version);
        }
        catch (IOException ex) {
            LOGGER.warn("Load version info failed.", ex);
        }
    }

    public static Point getWindowPos(String encodedWindowPosition) {
        try {
            if (StringUtils.isNotBlank(encodedWindowPosition)) {
                int[] tokens = new int[5];
                int index = 0;
                String[] st = encodedWindowPosition.split(",");
                while (index < tokens.length) {

                    tokens[index] = Integer.parseInt(st[index]);
                    index++;
                }

                return new Point(tokens[0], tokens[1]);
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Get encoded window position failed: {}", encodedWindowPosition, ex);
        }
        return null;
    }

    public static Dimension getWindowSize(String encodedWindowPosition) {
        try {
            if (StringUtils.isNotBlank(encodedWindowPosition)) {
                int[] tokens = new int[5];
                int index = 0;
                String[] st = encodedWindowPosition.split(",");
                while (index < tokens.length) {

                    tokens[index] = Integer.parseInt(st[index]);
                    index++;
                }

                return new Dimension(tokens[2], tokens[3]);
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Get encoded window size failed: {}", encodedWindowPosition, ex);
        }
        return null;
    }

    public static int getExtendedState(String encodedWindowPosition) {
        try {
            if (StringUtils.isNotBlank(encodedWindowPosition)) {
                int[] tokens = new int[5];
                int index = 0;
                String[] st = encodedWindowPosition.split(",");
                while (index < tokens.length) {

                    tokens[index] = Integer.parseInt(st[index]);
                    index++;
                }

                return tokens[4];
            }
        }
        catch (Exception ex) {
            LOGGER.warn("Get encoded window size failed: {}", encodedWindowPosition, ex);
        }
        return Frame.NORMAL;
    }

    public static String encodedWindowPosition(Point windowPosition, Dimension windowSize, int extendedState) {
        String encodedWindowPosition =
            String.format("%1$d,%2$d,%3$d,%4$d,%5$d", windowPosition.x, windowPosition.y, windowSize.width,
                windowSize.height, extendedState);
        return encodedWindowPosition;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy