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;
}
}