package net.floodlightcontroller.devicemanager.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField;
import net.floodlightcontroller.devicemanager.SwitchPort;
import com.fasterxml.jackson.annotation.JsonProperty;
public class DeviceSyncRepresentation {
public static class SyncEntity implements Comparable<SyncEntity> {
@JsonProperty
public long macAddress;
@JsonProperty
public Integer ipv4Address;
@JsonProperty
public Short vlan;
@JsonProperty
public Long switchDPID;
@JsonProperty
public Integer switchPort;
@JsonProperty
public Date lastSeenTimestamp;
@JsonProperty
public Date activeSince;
public SyncEntity() {
// do nothing;
}
public SyncEntity(Entity e) {
this.macAddress = e.getMacAddress();
this.ipv4Address = e.getIpv4Address();
this.vlan = e.getVlan();
this.switchDPID = e.getSwitchDPID();
this.switchPort = e.getSwitchPort();
if (e.getLastSeenTimestamp() == null)
this.lastSeenTimestamp = null;
else
this.lastSeenTimestamp = new Date(e.getLastSeenTimestamp().getTime());
if (e.getActiveSince() == null)
this.activeSince = null;
else
this.activeSince = new Date(e.getActiveSince().getTime());
}
public Entity asEntity() {
Entity e = new Entity(macAddress, vlan, ipv4Address, switchDPID,
switchPort, lastSeenTimestamp);
e.setActiveSince(activeSince);
return e;
}
@Override
public int compareTo(SyncEntity other) {
return lastSeenTimestamp.compareTo(other.lastSeenTimestamp);
}
@Override
public String toString() {
return asEntity().toString();
}
}
private String key;
private List<SyncEntity> entities;
public DeviceSyncRepresentation() {
// do nothing
}
public DeviceSyncRepresentation(Device device) {
this.key = computeKey(device);
this.entities = new ArrayList<SyncEntity>();
// FIXME: do we need the APs with errors as well??
// FIXME
SwitchPort[] aps = device.getAttachmentPoints();
for(Entity e: device.getEntities()) {
// Add the entities from the device only if they either don't
// have a switch/port or if they are an attachment point or
// if they have an IP address.
if (!e.hasSwitchPort()) {
this.entities.add(new SyncEntity(e));
} else if (isAttachmentPointEntity(aps, e)) {
this.entities.add(new SyncEntity(e));
} else if (e.getIpv4Address() != null) {
this.entities.add(new SyncEntity(e));
}
}
Collections.sort(this.entities);
}
private static boolean isAttachmentPointEntity(SwitchPort[] aps, Entity e) {
if (!e.hasSwitchPort())
return false;
for (SwitchPort p: aps) {
if (e.getSwitchDPID().equals(p.getSwitchDPID()) &&
e.getSwitchPort().equals(p.getPort())) {
return true;
}
}
return false;
}
static String computeKey(Device d) {
StringBuilder bld = new StringBuilder(d.getEntityClass().getName());
bld.append("::");
EnumSet<DeviceField> keyFields = d.getEntityClass().getKeyFields();
if (keyFields.contains(DeviceField.MAC)) {
bld.append(d.getMACAddressString());
bld.append("::");
}
if (keyFields.contains(DeviceField.VLAN)) {
if (d.getVlanId() != null)
bld.append(Arrays.toString(d.getVlanId()));
bld.append("::");
}
if (keyFields.contains(DeviceField.SWITCH) ||
keyFields.contains(DeviceField.PORT) ) {
if (d.getAttachmentPoints(true) != null)
bld.append(Arrays.toString(d.getAttachmentPoints(true)));
bld.append("::");
}
if (keyFields.contains(DeviceField.IPV4)) {
if (d.getIPv4Addresses() != null)
bld.append(Arrays.toString(d.getIPv4Addresses()));
bld.append("::");
}
return bld.toString();
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<SyncEntity> getEntities() {
return entities;
}
public void setEntities(List<SyncEntity> entities) {
if (entities == null) {
this.entities = null;
} else {
List<SyncEntity> tmp = new ArrayList<SyncEntity>(entities);
Collections.sort(tmp);
this.entities = tmp;
}
}
@Override
public String toString() {
return key;
}
}