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

org.bidib.wizard.common.node.AbstractPortHandler Maven / Gradle / Ivy

package org.bidib.wizard.common.node;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.bidib.jbidibc.messages.port.PortConfigValue;
import org.bidib.wizard.api.model.NodeChangePublisher;
import org.bidib.wizard.api.model.NodeInterface;
import org.bidib.wizard.api.model.event.NodeStatusEvent.StatusIdentifier;
import org.bidib.wizard.api.utils.PortListUtils;
import org.bidib.wizard.common.labels.WizardLabelWrapper;
import org.bidib.wizard.model.ports.GenericPort;
import org.bidib.wizard.model.ports.Port;
import org.bidib.wizard.model.ports.event.PortConfigEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractPortHandler> {

    private final Logger LOGGER = LoggerFactory.getLogger(getClass());

    protected List ports = new LinkedList<>();

    protected final NodeInterface node;

    protected boolean portsProcessed;

    private final Class portClazz;

    private final ConnectionNodeAwarePublisher publisher;

    private final WizardLabelWrapper wizardLabelWrapper;

    public AbstractPortHandler(final NodeInterface node, final ConnectionNodeAwarePublisher publisher,
        final WizardLabelWrapper wizardLabelWrapper) {
        this.node = node;
        this.publisher = publisher;
        this.portClazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        this.wizardLabelWrapper = wizardLabelWrapper;
    }

    protected ConnectionNodeAwarePublisher getPublisher() {
        return publisher;
    }

    protected final WizardLabelWrapper getWizardLabelWrapper() {
        return this.wizardLabelWrapper;
    }

    /**
     * Clear the ports.
     */
    public void clearPorts(final NodeChangePublisher nodeChangePublisher) {
        synchronized (ports) {

            LOGGER.info("Clear the ports.");
            ports.clear();

            portsProcessed = false;
        }

        // update port lists
        nodeChangePublisher.firePortListChanged(portClazz);
    }

    /**
     * @return node has ports
     */
    public boolean hasPorts() {
        LOGGER.debug("Check if ports are available.");
        synchronized (ports) {
            return CollectionUtils.isNotEmpty(ports);
        }
    }

    /**
     * Set the ports
     * 
     * @param ports
     *            the new ports.
     * @param nodeChangePublisher
     *            the node change publisher
     */
    public abstract void setPorts(List ports, final NodeChangePublisher nodeChangePublisher);

    /**
     * Get the switch ports.
     * 
     * @return the switch ports
     * @param nodeChangePublisher
     *            the node change publisher
     */
    public List getPorts(final NodeChangePublisher nodeChangePublisher) {

        // in the type-oriented model the switch ports are set
        // in the flat model the switch ports are fetched from the generic ports
        List cachedPorts = Collections.emptyList();

        if (node.isFlatPortModel()) {
            boolean fireChanged = false;
            final List genericPorts = new ArrayList<>(node.getGenericPorts());
            synchronized (genericPorts) {

                synchronized (ports) {
                    if (StatusIdentifier.InitialLoadFinished != node.getNodeLoadStatusIdentifier()
                    // TODO this was removed to keep the port identifiers
                    /* || (!portsProcessed && CollectionUtils.isNotEmpty(genericPorts)) */) {
                        LOGGER
                            .info("Clear and rebuild the ports cache. Current node load status: {}, node: {}",
                                node.getNodeLoadStatusIdentifier(), node);
                        // clear the cached ports
                        ports.clear();

                        cachePorts(genericPorts);

                        // we have to signal that the ports have changed
                        fireChanged = true;
                    }
                    else if (ports.isEmpty()) {
                        LOGGER.info("No cached ports available.");
                        cachePorts(genericPorts);

                        if (!ports.isEmpty()) {
                            // we have to signal that the ports have changed
                            fireChanged = true;
                        }
                    }
                    else {
                        LOGGER
                            .info("Return the cached {} ports, portsProcessed: {}", portClazz.getSimpleName(),
                                portsProcessed);
                    }

                    if (StatusIdentifier.InitialLoadFinished == node.getNodeLoadStatusIdentifier()) {
                        // set the flag
                        LOGGER.info("Set the portsProcessed flag to true for node: {}", node);
                        portsProcessed = true;
                    }

                    cachedPorts = Collections.unmodifiableList(ports);
                }
            }

            // signal the changes to the listeners
            if (fireChanged && StatusIdentifier.InitialLoadFinished == node.getNodeLoadStatusIdentifier()) {
                LOGGER.info("Fire that the ports have changed.");

                nodeChangePublisher.firePortListChanged(portClazz);
            }
        }
        else {
            LOGGER.debug("The current node supports the type-oriented port model: {}", node);
            cachedPorts = Collections.unmodifiableList(ports);
        }

        return cachedPorts;
    }

    protected abstract void cachePorts(final List genericPorts);

    /**
     * Set the configuration of the port.
     * 
     * @param portNumber
     *            the port number
     * @param portConfig
     *            the new port configuration
     * @param nodeChangePublisher
     *            the node change publisher
     */
    public void setPortConfig(
        int portNumber, Map> portConfig, final NodeChangePublisher nodeChangePublisher) {
        // synchronize because the ports can be accessed from different threads
        try {
            T port = null;
            synchronized (ports) {
                List currentPorts = getPorts(nodeChangePublisher);
                if (CollectionUtils.isNotEmpty(currentPorts)) {
                    port = PortListUtils.findPortByPortNumber(currentPorts, portNumber);
                    if (port != null && portConfig != null) {
                        port.setPortConfigX(portConfig);
                    }
                }
            }

            if (port != null) {
                final T portToNotify = port;
                nodeChangePublisher.firePortConfigChanged((Port) portToNotify);

                // TODO remove the node change publisher
                getPublisher()
                    .getSubjectPortEvents()
                    .onNext(new PortConfigEvent(getPublisher().getConnectionId(), getPublisher().getUniqueId(), port));

            }
        }
        catch (Exception ex) {
            LOGGER.warn("Set port config failed for portNumber: {}, portType: {}", portNumber, portClazz, ex);
        }
    }

    public abstract List getEnabledPorts();

    public boolean hasPendingPortStatus() {

        for (T port : getEnabledPorts()) {

            if (port.getStatus() == null) {
                return true;
            }
        }
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy