package net.floodlightcontroller.devicemanager.internal;
import java.util.EnumSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.floodlightcontroller.devicemanager.IDeviceService;
import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField;
/**
* This is a thin wrapper around {@link Entity} that allows overriding
* the behavior of {@link Object#hashCode()} and {@link Object#equals(Object)}
* so that the keying behavior in a hash map can be changed dynamically
* @author readams
*/
public class IndexedEntity {
protected EnumSet<DeviceField> keyFields;
protected Entity entity;
private int hashCode = 0;
protected static Logger logger =
LoggerFactory.getLogger(IndexedEntity.class);
/**
* Create a new {@link IndexedEntity} for the given {@link Entity} using
* the provided key fields.
* @param keyFields The key fields that will be used for computing
* {@link IndexedEntity#hashCode()} and {@link IndexedEntity#equals(Object)}
* @param entity the entity to wrap
*/
public IndexedEntity(EnumSet<DeviceField> keyFields, Entity entity) {
super();
this.keyFields = keyFields;
this.entity = entity;
}
/**
* Check whether this entity has non-null values in any of its key fields
* @return true if any key fields have a non-null value
*/
public boolean hasNonNullKeys() {
for (DeviceField f : keyFields) {
switch (f) {
case MAC:
return true;
case IPV4:
if (entity.ipv4Address != null) return true;
break;
case SWITCH:
if (entity.switchDPID != null) return true;
break;
case PORT:
if (entity.switchPort != null) return true;
break;
case VLAN:
if (entity.vlan != null) return true;
break;
}
}
return false;
}
@Override
public int hashCode() {
if (hashCode != 0) {
return hashCode;
}
final int prime = 31;
hashCode = 1;
for (DeviceField f : keyFields) {
switch (f) {
case MAC:
hashCode = prime * hashCode
+ (int) (entity.macAddress ^
(entity.macAddress >>> 32));
break;
case IPV4:
hashCode = prime * hashCode
+ ((entity.ipv4Address == null)
? 0
: entity.ipv4Address.hashCode());
break;
case SWITCH:
hashCode = prime * hashCode
+ ((entity.switchDPID == null)
? 0
: entity.switchDPID.hashCode());
break;
case PORT:
hashCode = prime * hashCode
+ ((entity.switchPort == null)
? 0
: entity.switchPort.hashCode());
break;
case VLAN:
hashCode = prime * hashCode
+ ((entity.vlan == null)
? 0
: entity.vlan.hashCode());
break;
}
}
return hashCode;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
IndexedEntity other = (IndexedEntity) obj;
if (!keyFields.equals(other.keyFields))
return false;
for (IDeviceService.DeviceField f : keyFields) {
switch (f) {
case MAC:
if (entity.macAddress != other.entity.macAddress)
return false;
break;
case IPV4:
if (entity.ipv4Address == null) {
if (other.entity.ipv4Address != null) return false;
} else if (!entity.ipv4Address.
equals(other.entity.ipv4Address)) return false;
break;
case SWITCH:
if (entity.switchDPID == null) {
if (other.entity.switchDPID != null) return false;
} else if (!entity.switchDPID.
equals(other.entity.switchDPID)) return false;
break;
case PORT:
if (entity.switchPort == null) {
if (other.entity.switchPort != null) return false;
} else if (!entity.switchPort.
equals(other.entity.switchPort)) return false;
break;
case VLAN:
if (entity.vlan == null) {
if (other.entity.vlan != null) return false;
} else if (!entity.vlan.
equals(other.entity.vlan)) return false;
break;
}
}
return true;
}
}