package iamrescue.communication.messages.updates; import iamrescue.communication.messages.Message; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.Property; public abstract class EntityUpdatedMessage extends Message { private short timestamp; private EntityID id; private Map<String, Property> updatedProperties = new HashMap<String, Property>(); private Entity object; protected final static Log log = LogFactory .getLog(EntityUpdatedMessage.class); /** * This creates a new update message. * * @param timestep * the timestep at which this message was created */ public EntityUpdatedMessage(short timestamp) { this.timestamp = timestamp; } public String toShortString() { return getMessageName() + "[s:" + getSenderAgentID() + ",t:" + timestamp + ",id:" + id + "]"; } /* * (non-Javadoc) * * @see * iamrescue.communication.messages.Message#getMessageContentsAsString() */ @Override public String getMessageContentsAsString() { StringBuffer sb = new StringBuffer(); sb.append("ID:"); sb.append(id); sb.append(",timestamp=:"); sb.append(timestamp); sb.append(",properties:<"); if (updatedProperties == null) { sb.append("null"); } else { for (Entry<String, Property> entry : updatedProperties.entrySet()) { sb.append('('); sb.append(entry.getValue()); sb.append(')'); } } return sb.toString(); } /** * Returns the ID of the object this update is about. * * @return The ID of the object. */ public EntityID getObjectID() { return id; } public Entity getObject() { return object; } /** * Should return a list of URNs of Properties that are relevant for this * message. Only relevant properties will be communicated, all other * properties are ignored * * @return */ public abstract List<String> getRelevantProperties(); /** * Gets the time at which the message was sent. * * @return the time at which the message was sent */ public final short getTimestamp() { return timestamp; } public final void addUpdatedProperty(Property property) { String propertyURN = property.getURN(); if (!getRelevantProperties().contains(propertyURN)) log.trace("Property " + property + " is not relevant for message " + getClass()); else { if (updatedProperties.containsKey(propertyURN)) throw new IllegalArgumentException("Property " + property + " has already been set on this message. NewValue " + property.getValue() + " OldValue " + updatedProperties.get(property)); updatedProperties.put(propertyURN, property); } } public final void removeUpdatedProperty(String propertyURN) { if (!getRelevantProperties().contains(propertyURN)) { log.trace("Property " + propertyURN + " is not relevant for message " + getClass()); } else { Property removed = updatedProperties.remove(propertyURN); if (removed == null) { log.warn("Attempted to remove non-existant property " + propertyURN + " from message " + this); } } } // public boolean providesOwnCodec(String propertyURN) { // / return false; // } // public PropertyCodec getOwnCodec(String propertyURN) { // throw new IllegalArgumentException("No own codec for: " + propertyURN); // } public final Set<String> getChangedProperties() { return updatedProperties.keySet(); } public final boolean isPropertyChanged(String property) { return updatedProperties.containsKey(property); } public Property getProperty(String property) { return updatedProperties.get(property); } public Collection<Property> getProperties() { return updatedProperties.values(); } // @Override // public final boolean equals(Object obj) { // if (obj instanceof UpdateMessage) { // UpdateMessage message = (UpdateMessage) obj; // // if (message.getMessagePrefix() == getMessagePrefix()) { // if (message.updatedProperties.keySet().equals( // updatedProperties.keySet())) { // for (Property property : message.updatedProperties.keySet()) { // Object object1 = message.updatedProperties // .get(property); // Object object2 = updatedProperties.get(property); // // if (object1 instanceof Number) { // if (object2 instanceof Number) { // if (!iamrescue.util.NumberUtils.almostEquals( // (Number) object1, (Number) object2, // 0.05, 30)) // return false; // } else { // return false; // } // } // } // return true; // } // } // return false; // } // // return false; // } protected final byte getMessagePrefix() { return getCodec().getMessagePrefix(); } public void setObject(Entity object) { if (object != null) { if (!isCorrectObjectClass(object)) { throw new IllegalArgumentException( "Object is not of correct type " + object + ". Message class " + getClass()); } this.object = object; this.id = object.getID(); } } protected abstract boolean isCorrectObjectClass(Entity object); private void copyProperties(EntityUpdatedMessage message) { message.id = id; message.updatedProperties = updatedProperties; message.timestamp = timestamp; message.object = object; super.copyProperties(message); } @Override public final Message copy() { EntityUpdatedMessage message = createMessage(getTimestamp()); copyProperties(message); return message; } protected abstract EntityUpdatedMessage createMessage(short timestamp); }