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

org.bidib.wizard.dcca.client.model.DccAdvModel Maven / Gradle / Ivy

There is a newer version: 2.0.29
Show newest version
package org.bidib.wizard.dcca.client.model;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.SwingUtilities;

import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.bidib.jbidibc.core.schema.UserDevicesListFactory;
import org.bidib.jbidibc.core.schema.decoder.commontypes.DecoderTypeType;
import org.bidib.jbidibc.core.schema.decoder.userdevices.UserDeviceType;
import org.bidib.jbidibc.core.schema.decoder.userdevices.UserDevicesList;
import org.bidib.jbidibc.messages.DccAInfoIndexedString;
import org.bidib.jbidibc.messages.DccAInfoShortGui;
import org.bidib.jbidibc.messages.DccAInfoShortInfo;
import org.bidib.jbidibc.messages.DecoderIdAddressData;
import org.bidib.jbidibc.messages.enums.DccAOpCodeBm;
import org.bidib.jbidibc.messages.enums.DccAdvLogonType;
import org.bidib.wizard.api.model.NodeProvider;
import org.bidib.wizard.dcca.client.controller.listener.DccAdvDecoderActionListener;
import org.bidib.wizard.dcca.client.model.DccAdvDecoderModel.DetectionStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoodies.binding.beans.Model;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.ObservableElementList;

/**
 * This model is used to hold the configuration and current state of the DccAdv decoders that were detected in the
 * system.
 *
 */
public class DccAdvModel extends Model {

    private static final long serialVersionUID = 1L;

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

    private static final int DECODER_MIN_ADDRESS = 4;

    private static final int DECODER_MAX_ADDRESS = 10239;

    public static final String PROPERTY_DECODERS = "decoders";

    public static final String PROPERTY_COMMANDSTATION_ID = "commandStationId";

    public static final String PROPERTY_SESSION_ID = "sessionId";

    public static final String PROPERTY_POWERUSERMODE = "powerUserMode";

    public static final String PROPERTY_DCCADVLOGONTYPE = "dccAdvLogonType";

    public static final String PROPERTY_REPETITIONS = "repetitions";

    public static final String PROPERTY_LOGONENABLE_INTERVAL = "logonEnableInterval";

    public static final String PROPERTY_INIT_PASSED = "initPassed";

    public static final String PROPERTY_AUTO_ASSIGN_ENABLED = "autoAssignEnabled";

    private ObservableElementList activeDecoderList =
        new ObservableElementList<>(GlazedLists.eventList(new ArrayList<>()),
            GlazedLists.beanConnector(DccAdvDecoderModel.class));

    private ObservableElementList passiveDecoderList =
        new ObservableElementList<>(GlazedLists.eventList(new ArrayList<>()),
            GlazedLists.beanConnector(DccAdvDecoderModel.class));

    private Integer commandStationId;

    private Integer sessionId;

    private boolean powerUserMode;

    private DccAdvLogonType dccAdvLogonType = DccAdvLogonType.DCCA_ALL;

    private Integer repetitions = 1;

    private Integer logonEnableInterval = 0;

    private AtomicBoolean sendLogonEnableActive = new AtomicBoolean();

    private boolean initPassed;

    private boolean autoAssignEnabled = true;

    private PropertyChangeListener decoderChangeListener;

    private SortedSet availableDecoderAddresses = new TreeSet<>();

    private NodeProvider nodeProvider;

    public DccAdvModel() {
    }

    public void initialize(final DccAdvDecoderActionListener dccAdvDecoderActionListener) {

        // initialize the available decoder addresses
        for (int addr = DECODER_MIN_ADDRESS; addr < DECODER_MAX_ADDRESS; addr++) {
            availableDecoderAddresses.add(Integer.valueOf(addr));
        }

        // prepare the detection status change listener
        decoderChangeListener = new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                LOGGER.info("The decoder has changed: {}, property: {}", evt.getSource(), evt.getPropertyName());

                DccAdvDecoderModel decoder = null;
                switch (evt.getPropertyName()) {
                    case DccAdvDecoderModel.PROPERTY_DECODER_WISH_ADDRESS:

                        if (!isAutoAssignEnabled()) {
                            LOGGER.info("Auto-Assign is disabled.");
                            return;
                        }

                        decoder = (DccAdvDecoderModel) evt.getSource();
                        if (decoder.getDecoderWishAddress() != null) {
                            // check if the decoder wish address is available
                            int decoderWishAddress = decoder.getDecoderWishAddress();
                            int searchAddress = decoder.getDecoderWishAddress();
                            Integer addressToAssign = null;
                            boolean available = false;
                            do {
                                available = availableDecoderAddresses.remove(searchAddress);
                                LOGGER
                                    .info("Check if the decoder wish address is available, address: {}, available: {}",
                                        searchAddress, available);

                                if (available) {
                                    addressToAssign = searchAddress;
                                    break;
                                }

                                searchAddress++;
                            }
                            while (!available && searchAddress <= DECODER_MAX_ADDRESS);

                            // if no free address was found, we should from the begin up to the decoder wish address
                            if (addressToAssign == null && decoderWishAddress > DECODER_MIN_ADDRESS) {

                                // decoderWishAddress = decoder.getDecoderWishAddress();
                                searchAddress = DECODER_MIN_ADDRESS;
                                do {
                                    available = availableDecoderAddresses.remove(searchAddress);
                                    LOGGER
                                        .info(
                                            "Check if the decoder wish address is available, address: {}, available: {}",
                                            searchAddress, available);

                                    if (available) {
                                        addressToAssign = searchAddress;
                                        break;
                                    }

                                    searchAddress++;
                                }
                                while (!available && searchAddress < decoderWishAddress);
                            }

                            if (addressToAssign != null) {
                                LOGGER.info("Found available address to assign: {}", addressToAssign);
                                decoder.setDecoderAddress(addressToAssign);

                                // now assign
                                dccAdvDecoderActionListener.assignAddress(decoder);
                            }
                            else {
                                LOGGER
                                    .warn("No free address to assign for decoder: {}, decoderWishAddress: {}", decoder,
                                        decoderWishAddress);
                            }
                        }
                        else {
                            LOGGER.info("No wish address available.");
                        }
                        break;
                    case DccAdvDecoderModel.PROPERTY_DETECTIONSTATUS:
                        decoder = (DccAdvDecoderModel) evt.getSource();
                        if (DetectionStatus.ASSIGNED != evt.getOldValue()
                            && DetectionStatus.ASSIGNED == evt.getNewValue()) {
                            LOGGER
                                .info("The decoder was assigned to address: {}. Turn the lights on!",
                                    decoder.getDecoderAddress());

                            dccAdvDecoderActionListener.setSpeedAndLight(decoder, 0, true);
                        }
                        break;
                    default:
                        break;
                }

            }
        };
    }

    /**
     * @param nodeProvider
     *            the node provider
     */
    public void setNodeProvider(final NodeProvider nodeProvider) {
        LOGGER.info("Set the node provider: {}", nodeProvider);
        this.nodeProvider = nodeProvider;
    }

    /**
     * @return the nodeProvider
     */
    public NodeProvider getNodeProvider() {
        return nodeProvider;
    }

    public void setUserDevicesList(final UserDevicesList userDevicesList) {
        // keep the list

        if (userDevicesList != null && userDevicesList.getUserDevices() != null) {
            List locoDevices =
                UserDevicesListFactory
                    .findUserDevices(DecoderTypeType.LOCO, userDevicesList.getUserDevices().getUserDevice());

            for (UserDeviceType locoDevice : locoDevices) {
                addLoco(passiveDecoderList, locoDevice);
            }
        }
    }

    private void addLoco(List decoderList, final UserDeviceType locoDevice) {

        synchronized (decoderList) {
            LOGGER.info("Add the locoDevice: {}", locoDevice);

            Integer locoAddress = locoDevice.getAddress();

            DecoderIdAddressData decoderUniqueData = null;
            if (locoDevice.getDecoder() != null) {
                // get the data from the stored decoder data
                String decoderId = locoDevice.getDecoder().getDecoderId();
                short manufacturerId = locoDevice.getDecoder().getManufacturerId();

                if (StringUtils.isNotBlank(decoderId)) {
                    long decoderUniqueId = Long.parseLong(decoderId);

                    decoderUniqueData = new DecoderIdAddressData(decoderUniqueId, (int) manufacturerId);

                    LOGGER
                        .info("Found decoderId in userDevices: {}, manufacturerId: {}", decoderUniqueId,
                            manufacturerId);
                }
            }

            DccAdvDecoderModel loco = updateDecoderList(decoderList, decoderUniqueData, locoAddress);
            if (loco != null) {
                loco.setShortName(new DccAInfoIndexedString(0, locoDevice.getName()));
            }
        }

    }

    /**
     * @return the active decoderList model
     */
    public EventList getActiveDecoderListModel() {
        return activeDecoderList;
    }

    /**
     * @return the passive decoderList model
     */
    public EventList getPassiveDecoderListModel() {
        return passiveDecoderList;
    }

    public DccAdvDecoderModel updateDecoderList(final DecoderIdAddressData locoDecoderUniqueId, Integer locoAddress) {
        LOGGER
            .info("Update the active decoder list, locoDecoderUniqueId: {}, locoAddress: {}", locoDecoderUniqueId,
                locoAddress);

        return updateDecoderList(activeDecoderList, locoDecoderUniqueId, locoAddress);
    }

    /**
     * Update the decoder with the provided data or create new decoder model.
     * 
     * @param decoderList
     *            the decoder list
     * @param locoDecoderUniqueId
     *            the did of the decoder
     * @param locoAddress
     *            the loco address
     * @return the selected decoder model
     */
    private DccAdvDecoderModel updateDecoderList(
        List decoderList, final DecoderIdAddressData locoDecoderUniqueId, Integer locoAddress) {

        DccAdvDecoderModel decoder = IterableUtils.find(decoderList, new Predicate() {

            @Override
            public boolean evaluate(DccAdvDecoderModel currentInstance) {

                if (locoDecoderUniqueId != null) {
                    Long decoderUniqueId = currentInstance.getDecoderDid();
                    Integer manufacturerId = currentInstance.getManufacturerId();
                    if (decoderUniqueId != null && manufacturerId != null) {
                        // compare the decoderUnique and the manufacturer
                        if (Objects.equals(locoDecoderUniqueId.getDid(), decoderUniqueId)
                            && Objects.equals(locoDecoderUniqueId.getManufacturedId(), manufacturerId)) {
                            LOGGER.info("Found matching decoder: {}", currentInstance);
                            return true;
                        }
                    }
                }

                if (locoAddress != null) {
                    Integer address = currentInstance.getDecoderAddress();
                    return address != null && address == locoAddress;
                }
                return false;
            }
        });

        //
        if (decoder == null && decoderList == activeDecoderList) {
            // check if we find the decoder in the passiveDecoderList
            decoder = IterableUtils.find(passiveDecoderList, new Predicate() {

                @Override
                public boolean evaluate(DccAdvDecoderModel currentInstance) {

                    if (locoDecoderUniqueId != null) {
                        Long decoderUniqueId = currentInstance.getDecoderDid();
                        Integer manufacturerId = currentInstance.getManufacturerId();
                        if (decoderUniqueId != null && manufacturerId != null) {
                            // compare the decoderUnique and the manufacturer
                            if (Objects.equals(locoDecoderUniqueId.getDid(), decoderUniqueId)
                                && Objects.equals(locoDecoderUniqueId.getManufacturedId(), manufacturerId)) {
                                LOGGER.info("Found matching decoder in passive decoder list: {}", currentInstance);
                                return true;
                            }
                        }
                    }

                    if (locoAddress != null) {
                        Integer address = currentInstance.getDecoderAddress();
                        return address != null && address == locoAddress;
                    }
                    return false;
                }
            });

            if (decoder != null) {
                // move to active decoder list
                LOGGER.info("Move the decoder from passive to active list: {}", decoder);
                passiveDecoderList.remove(decoder);
                activeDecoderList.add(decoder);

                if (locoDecoderUniqueId != null) {
                    decoder.setDetectionStatus(DetectionStatus.NEW_DID);
                }
            }
        }

        if (decoder == null) {
            decoder = new DccAdvDecoderModel();

            if (locoAddress != null) {
                decoder.setDecoderAddress(locoAddress);
            }
            if (locoDecoderUniqueId != null) {
                decoder.setDecoderUniqueId(locoDecoderUniqueId);
                if (decoderList == activeDecoderList) {
                    decoder.setDetectionStatus(DetectionStatus.NEW_DID);
                }
            }

            addDecoder(decoderList, decoder);
        }

        return decoder;
    }

    public void addDecoder(List decoderList, final DccAdvDecoderModel decoder) {
        synchronized (decoderList) {
            if (!decoderList.contains(decoder)) {
                LOGGER.info("Add decoder to decoder list: {}", decoder);

                if (SwingUtilities.isEventDispatchThread()) {
                    List oldValue = new LinkedList<>(decoderList);

                    decoderList.add(decoder);

                    decoder.addPropertyChangeListener(decoderChangeListener);

                    firePropertyChange(PROPERTY_DECODERS, oldValue, decoderList);
                }
                else {
                    SwingUtilities.invokeLater(() -> {
                        List oldValue = new LinkedList<>(decoderList);

                        decoderList.add(decoder);

                        decoder.addPropertyChangeListener(decoderChangeListener);

                        firePropertyChange(PROPERTY_DECODERS, oldValue, decoderList);
                    });
                }

            }
            else {
                LOGGER.warn("Decoder is already in decoder list: {}", decoder);
            }
        }
    }

    public void removeDecoder(DccAdvDecoderModel decoder) {
        synchronized (activeDecoderList) {
            LOGGER.info("Remove decoder from decoder list: {}", decoder);

            List oldValue = new LinkedList<>(activeDecoderList);
            boolean removed = activeDecoderList.remove(decoder);

            if (removed) {
                decoder.removePropertyChangeListener(decoderChangeListener);

                firePropertyChange(PROPERTY_DECODERS, oldValue, activeDecoderList);
            }
            else {
                LOGGER.warn("Decoder was not removed from decoder list: {}", decoder);
            }
        }
    }

    public DccAdvDecoderModel findDecoder(final Long searchDecoderUniqueId) {

        DccAdvDecoderModel decoder = null;

        LOGGER.info("Search decoder in decoder list: {}, searchDecoderUniqueId: {}", decoder, searchDecoderUniqueId);

        synchronized (activeDecoderList) {

            decoder = IterableUtils.find(activeDecoderList, new Predicate() {

                @Override
                public boolean evaluate(DccAdvDecoderModel dec) {
                    if (dec.getDecoderDid() == searchDecoderUniqueId) {
                        return true;
                    }
                    return false;
                }
            });
        }

        LOGGER.info("find decoder returns: {}", decoder);
        return decoder;
    }

    public void decoderChanged(DccAdvDecoderModel decoder) {
        int index = activeDecoderList.indexOf(decoder);
        if (index > -1) {
            // activeDecoderList.fireContentsChanged(index);
        }
        else {
            LOGGER.warn("Decoder not found in model: {}", decoder);
        }
    }

    /**
     * @return the commandStationId
     */
    public Integer getCommandStationId() {
        return commandStationId;
    }

    /**
     * @param commandStationId
     *            the commandStationId to set
     */
    public void setCommandStationId(Integer commandStationId) {
        LOGGER.info("Set the commandStationId: {}", commandStationId);
        Integer oldValue = this.commandStationId;
        this.commandStationId = commandStationId;
        firePropertyChange(PROPERTY_COMMANDSTATION_ID, oldValue, this.commandStationId);
    }

    /**
     * @return the sessionId
     */
    public Integer getSessionId() {
        return sessionId;
    }

    /**
     * @param sessionId
     *            the sessionId to set
     */
    public void setSessionId(Integer sessionId) {
        LOGGER.info("Set the sessionId: {}", sessionId);
        Integer oldValue = this.sessionId;
        this.sessionId = sessionId;
        firePropertyChange(PROPERTY_SESSION_ID, oldValue, this.sessionId);
        checkCanOperate();
    }

    private void checkCanOperate() {
        if (sessionId != null && commandStationId != null && logonEnableInterval != null && repetitions != null) {
            setInitPassed(true);
        }
        else {
            setInitPassed(false);
        }
    }

    /**
     * @return the powerUserMode
     */
    public boolean isPowerUserMode() {
        return powerUserMode;
    }

    /**
     * @param powerUserMode
     *            the powerUserMode to set
     */
    public void setPowerUserMode(boolean powerUserMode) {
        LOGGER.info("Set the powerUserMode: {}", powerUserMode);
        boolean oldValue = this.powerUserMode;
        this.powerUserMode = powerUserMode;
        firePropertyChange(PROPERTY_POWERUSERMODE, oldValue, this.powerUserMode);
    }

    /**
     * @return the dccAdvLogonType
     */
    public DccAdvLogonType getDccAdvLogonType() {
        return dccAdvLogonType;
    }

    /**
     * @param dccAdvLogonType
     *            the dccAdvLogonType to set
     */
    public void setDccAdvLogonType(DccAdvLogonType dccAdvLogonType) {
        LOGGER.info("Set the dccAdvLogonType: {}", dccAdvLogonType);
        DccAdvLogonType oldValue = this.dccAdvLogonType;
        this.dccAdvLogonType = dccAdvLogonType;
        firePropertyChange(PROPERTY_DCCADVLOGONTYPE, oldValue, this.dccAdvLogonType);
    }

    /**
     * @return the repetitions
     */
    public Integer getRepetitions() {
        return repetitions;
    }

    /**
     * @param repetitions
     *            the repetitions to set
     */
    public void setRepetitions(Integer repetitions) {
        LOGGER.info("Set the repetitions: {}", repetitions);
        Integer oldValue = this.repetitions;
        this.repetitions = repetitions;
        firePropertyChange(PROPERTY_REPETITIONS, oldValue, this.repetitions);
        checkCanOperate();
    }

    /**
     * @return the logonEnableInterval
     */
    public Integer getLogonEnableInterval() {
        return logonEnableInterval;
    }

    /**
     * @param logonEnableInterval
     *            the logonEnableInterval to set
     */
    public void setLogonEnableInterval(Integer logonEnableInterval) {
        LOGGER.info("Set the logonEnableInterval: {}", logonEnableInterval);
        Integer oldValue = this.logonEnableInterval;
        this.logonEnableInterval = logonEnableInterval;
        firePropertyChange(PROPERTY_LOGONENABLE_INTERVAL, oldValue, this.logonEnableInterval);
        checkCanOperate();
    }

    /**
     * @return the sendLogonEnableActive
     */
    public boolean isSendLogonEnableActive() {
        return sendLogonEnableActive.get();
    }

    /**
     * @param sendLogonEnableActive
     *            the sendLogonEnableActive to set
     */
    public void setSendLogonEnableActive(boolean sendLogonEnableActive) {
        this.sendLogonEnableActive.set(sendLogonEnableActive);
    }

    /**
     * @return the initPassed
     */
    public boolean isInitPassed() {
        return initPassed;
    }

    /**
     * @param initPassed
     *            the initPassed to set
     */
    public void setInitPassed(boolean initPassed) {
        boolean oldValue = this.initPassed;
        this.initPassed = initPassed;
        firePropertyChange(PROPERTY_INIT_PASSED, oldValue, this.initPassed);
    }

    /**
     * @return the autoAssignEnabled flag
     */
    public boolean isAutoAssignEnabled() {
        return autoAssignEnabled;
    }

    /**
     * @param autoAssignEnabled
     *            the autoAssignEnabled flag
     */
    public void setAutoAssignEnabled(boolean autoAssignEnabled) {
        boolean oldValue = this.autoAssignEnabled;
        this.autoAssignEnabled = autoAssignEnabled;
        firePropertyChange(PROPERTY_AUTO_ASSIGN_ENABLED, oldValue, this.autoAssignEnabled);
    }

    /**
     * Update the shortName of the decoder.
     * 
     * @param decoderIdAddressData
     *            the did
     * @param shortName
     *            the shortName
     * @return {@code true}: decoder was found, {@code false} decoder was not found
     */
    public boolean updateDecoderShortName(DecoderIdAddressData decoderIdAddressData, DccAInfoIndexedString shortName) {
        LOGGER
            .info("Process the received short name data, decoderIdAddressData: {}, shortName: {}", decoderIdAddressData,
                shortName);

        // update the shortname of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the shortName on decoder: {}, shortName: {}", decoder, shortName);
                decoder.setShortName(shortName);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_SHORTNAME)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }
            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

        return false;
    }

    /**
     * Update the shortInfo of the decoder.
     * 
     * @param decoderIdAddressData
     *            the did
     * @param shortInfo
     *            the shortInfo
     * @return {@code true}: decoder was found, {@code false} decoder was not found
     */
    public boolean updateDecoderShortInfo(DecoderIdAddressData decoderIdAddressData, DccAInfoShortInfo shortInfo) {
        LOGGER
            .info("Process the received short info data, decoderIdAddressData: {}, shortInfo: {}", decoderIdAddressData,
                shortInfo);

        // update the shortInfo of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the shortInfo on decoder: {}, shortName: {}", decoder, shortInfo);
                decoder.setShortInfo(shortInfo);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_SHORTINFO)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }
            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }
        return false;
    }

    /**
     * Update the shortGui of the decoder.
     * 
     * @param decoderIdAddressData
     *            the did
     * @param shortGui
     *            the shortGui
     * @return {@code true}: decoder was found, {@code false} decoder was not found
     */
    public boolean updateDecoderShortGui(DecoderIdAddressData decoderIdAddressData, DccAInfoShortGui shortGui) {
        LOGGER
            .info("Process the received short gui data, decoderIdAddressData: {}, shortGui: {}", decoderIdAddressData,
                shortGui);

        // update the shortGui of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the shortGui on decoder: {}, shortName: {}", decoder, shortGui);
                decoder.setShortGui(shortGui);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_SHORTGUI)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }
            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

        return false;
    }

    public boolean updateDecoderFullName(DecoderIdAddressData decoderIdAddressData, DccAInfoIndexedString fullName) {
        LOGGER
            .info("Process the received full name data, decoderIdAddressData: {}, fullName: {}", decoderIdAddressData,
                fullName);

        // update the fullname of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the fullName on decoder: {}, fullName: {}", decoder, fullName);
                decoder.setFullName(fullName);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_FULLNAME)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }
            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

        return false;
    }

    public boolean updateDecoderProductName(
        DecoderIdAddressData decoderIdAddressData, DccAInfoIndexedString productName) {
        LOGGER
            .info("Process the received product name data, decoderIdAddressData: {}, productName: {}",
                decoderIdAddressData, productName);

        // update the product name of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the productName on decoder: {}, productName: {}", decoder, productName);
                decoder.setProductName(productName);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_PRODUCTNAME)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }
            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

        return false;
    }

    public boolean updateDecoderFirmwareId(
        DecoderIdAddressData decoderIdAddressData, DccAInfoIndexedString firmwareId) {
        LOGGER
            .info("Process the received firmware id data, decoderIdAddressData: {}, firmwareId: {}",
                decoderIdAddressData, firmwareId);

        // update the firmwareId of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            synchronized (decoder) {
                LOGGER.info("Set the firmwareId on decoder: {}, firmwareId: {}", decoder, firmwareId);
                decoder.setFirmwareId(firmwareId);

                if (decoder.checkAllDataReceived(DccAOpCodeBm.BIDIB_DCCA_INFO_FIRMWAREID)) {
                    triggerCheckDataCompleteLock(decoder);
                }
            }

            return true;
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

        return false;
    }

    public void updateLogonAssign(DecoderIdAddressData decoderIdAddressData, DetectionStatus detectionStatus) {
        // update the logon assign status of the decoder in the active decoder list
        DccAdvDecoderModel decoder = findDecoderByDid(activeDecoderList, decoderIdAddressData);
        if (decoder != null) {
            LOGGER.info("Set the logonAssign on decoder: {}, detectionStatus: {}", decoder, detectionStatus);
            synchronized (decoder) {
                decoder.setDetectionStatus(detectionStatus);
            }
        }
        else {
            LOGGER.warn("No matching decoder found in active decoder list.");
        }

    }

    private DccAdvDecoderModel findDecoderByDid(
        final List decoderList, final DecoderIdAddressData did) {
        DccAdvDecoderModel loco = IterableUtils.find(decoderList, new Predicate() {

            @Override
            public boolean evaluate(DccAdvDecoderModel currentInstance) {

                Long decoderUniqueId = currentInstance.getDecoderDid();
                Integer manufacturerId = currentInstance.getManufacturerId();
                if (decoderUniqueId != null && manufacturerId != null) {
                    // compare the decoderUnique and the manufacturer
                    if (Objects.equals(did.getDid(), decoderUniqueId)
                        && Objects.equals(did.getManufacturedId(), manufacturerId)) {
                        LOGGER.info("Found matching decoder: {}", currentInstance);
                        return true;
                    }
                }
                return false;
            }
        });
        return loco;
    }

    private void triggerCheckDataCompleteLock(final DccAdvDecoderModel decoder) {
        LOGGER.info("Trigger the checkDataComplete lock of decoder: {}", decoder);

        synchronized (decoder.getCheckDataCompleteLock()) {
            decoder.getCheckDataCompleteLock().notifyAll();
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy