/**
*
*/
package iamrescue.belief.commupdates;
import iamrescue.belief.IAMWorldModel;
import iamrescue.belief.provenance.AgentCommunicationOrigin;
import iamrescue.belief.provenance.IPropertyMerger;
import iamrescue.belief.provenance.ProvenanceLogEntry;
import iamrescue.communication.messages.Message;
import iamrescue.communication.messages.updates.EntityUpdatedMessage;
import java.util.Arrays;
import java.util.Collection;
import org.apache.log4j.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardPropertyURN;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.Property;
import rescuecore2.worldmodel.properties.EntityRefListProperty;
/**
* @author Sebastian
*
*/
public class EntityUpdateHandler implements IMessageHandler {
private static final Logger LOGGER = Logger
.getLogger(EntityUpdateHandler.class);
private IAMWorldModel worldModel;
private IPropertyMerger propertyMerger;
// private ISpatialIndex spatial;
public EntityUpdateHandler(IAMWorldModel worldModel,
IPropertyMerger propertyMerger) {// , ISpatialIndex spatial) {
this.worldModel = worldModel;
this.propertyMerger = propertyMerger;
// this.spatial = spatial;
}
@Override
public boolean canHandle(Message message) {
return (message instanceof EntityUpdatedMessage);
}
@Override
public boolean handleMessage(Message message) {
boolean updated = false;
EntityUpdatedMessage updateMsg = (EntityUpdatedMessage) message;
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Updating world model with " + updateMsg);
}
StandardEntity existingEntity = worldModel.getEntity(updateMsg
.getObjectID());
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Existing entity: " + updateMsg);
}
if (existingEntity == null) {
// Did I know about this in the past?
Collection<String> provenanceProperties = worldModel
.getProvenanceProperties(updateMsg.getObjectID());
if (provenanceProperties.size() > 0) {
LOGGER.debug("Ignoring message about an object "
+ "that was previously deleted from belief base: "
+ updateMsg);
updateMsg.markAsRead();
return updated;
}
// Create entity
worldModel.addEntity(updateMsg.getObject());
existingEntity = worldModel.getEntity(updateMsg.getObjectID());
}
/*
* Integer x = null; Integer y = null; boolean positionIncluded = false;
*/
for (Property p : updateMsg.getProperties()) {
// update provenance
ProvenanceLogEntry entry = new ProvenanceLogEntry(updateMsg
.getTimestamp(), AgentCommunicationOrigin.get(updateMsg
.getChannel()), p.copy());
worldModel.storeProvenance(updateMsg.getObjectID(), entry);
// update current value in belief base
Property decidedValue = propertyMerger.decideValue(worldModel
.getProvenance(updateMsg.getObjectID(), p.getURN()));
Property existingProperty = existingEntity.getProperty(p.getURN());
// Check if blockades need to be removed:
if (existingProperty.getURN().equals(StandardPropertyURN.BLOCKADES)) {
if (existingProperty.isDefined() && decidedValue.isDefined()) {
EntityRefListProperty blocks = (EntityRefListProperty) existingProperty;
EntityRefListProperty blocksNew = (EntityRefListProperty) decidedValue;
for (EntityID id : blocks.getValue()) {
if (!(blocksNew.getValue().contains(id))) {
worldModel.removeEntity(id);
}
}
}
}
if (existingProperty.isDefined()) {
if (!decidedValue.isDefined()) {
updated = true;
} else {
// Both defined. Check if they are not equal.
if (!IAMWorldModel.checkIfPropertiesEqual(existingProperty,
decidedValue)) {
updated = true;
}
}
} else {
if (decidedValue.isDefined()) {
updated = true;
}
}
existingProperty.takeValue(decidedValue);
/*
* if (existingEntity instanceof Human && p.isDefined()) { if
* (p.getURN().equals(StandardPropertyURN.X.toString())) { x =
* (Integer) p.getValue(); } else if
* (p.getURN().equals(StandardPropertyURN.Y.toString())) { y =
* (Integer) p.getValue(); } else if (p.getURN().equals(
* StandardPropertyURN.POSITION.toString())) { positionIncluded =
* true; } }
*/
}
// If x and y were communicated but not position, try to infer this
/*
* if (existingEntity instanceof Human && !positionIncluded) { if (x !=
* null && y != null) { Collection<StandardEntity> query = spatial
* .query(SpatialQueryFactory.queryWithinDistance( new
* PositionXY(x.intValue(), y.intValue()), 0, Building.class)); if
* (query.size() == 0) {
* LOGGER.warn("Could not infer location of entity " +
* existingEntity.getFullDescription()); } else if (query.size() > 1) {
* StandardEntity first = query.iterator().next(); LOGGER.warn("Entity "
* + existingEntity.getFullDescription() +
* " has multiple potential locations. " + "Choosing first: " +
* first.getFullDescription()); Property existingPosition =
* existingEntity.getProperty(StandardPropertyURN.POSITION .toString());
*
* } } }
*/
updateMsg.markAsRead();
return updated;
}
}