package com.walkertribe.ian.iface;

import java.util.Collections;
import java.util.List;

import com.walkertribe.ian.protocol.ArtemisPacket;
import com.walkertribe.ian.protocol.ArtemisPacketException;
import com.walkertribe.ian.protocol.core.world.ObjectUpdatePacket;
import com.walkertribe.ian.world.ArtemisObject;

/**
 * Object which reports the results of a packet parsing attempt.
 * @author rjwut
 */
public class ParseResult {
	private ArtemisPacket packet;
	private List<ListenerMethod> interestedPacketListeners = Collections.emptyList();
	private List<ListenerMethod> interestedObjectListeners = Collections.emptyList();
	private ArtemisPacketException exception;

	ParseResult() {
		// make constructor accessible only to the package
	}

	/**
	 * Returns the packet object generated by the parse attempt.
	 */
	public ArtemisPacket getPacket() {
		return packet;
	}

	/**
	 * Sets the packet object generated by the parse attempt.
	 */
	void setPacket(ArtemisPacket packet) {
		this.packet = packet;
	}

	/**
	 * Adds a ListenerMethod that is interested in the packet.
	 */
	void setPacketListeners(List<ListenerMethod> listeners) {
		interestedPacketListeners = listeners;
	}

	/**
	 * Adds a ListenerMethod that is interested in the objects in the packet.
	 * (Applies only to ObjectUpdatePackets.)
	 */
	void setObjectListeners(List<ListenerMethod> listeners) {
		interestedObjectListeners = listeners;
	}

	/**
	 * Return any exception that occurred while parsing the packet. Note that
	 * this doesn't handle exceptions that occur before the payload is read,
	 * since in that case, IAN will not have gotten far enough along to even
	 * produce a ParseResult.
	 */
	public ArtemisPacketException getException() {
		return exception;
	}

	/**
	 * Sets the exception that occurred during the parsing of this packet. This
	 * is only for non-fatal exceptions. A fatal exception (one occuring before
	 * the payload can be read) should cause the exception to be thrown
	 * instead.
	 */
	void setException(ArtemisPacketException exception) {
		this.exception = exception;
	}

	/**
	 * Convenience method for isInterestingPacket() || isInterestingObject().
	 */
	public boolean isInteresting() {
		return !(interestedPacketListeners.isEmpty() && interestedObjectListeners.isEmpty());
	}

	/**
	 * Returns true if the packet was of interest to any listeners. Note that in
	 * the case of an ObjectUpdatePacket, there may be listeners that aren't
	 * interested in the packet itself, but are interested in certain types of
	 * objects the packet may contain. Thus, it's entirely possible for
	 * isInterestingPacket() to return false while isContainsInterestingObject()
	 * returns true.
	 */
	public boolean isInterestingPacket() {
		return !interestedPacketListeners.isEmpty();
	}

	/**
	 * Returns true if the packet is an ObjectUpdatePacket and it contains an
	 * object of interest to one or more listeners.
	 */
	public boolean isContainsInterestingObject() {
		return !interestedObjectListeners.isEmpty();
	}

	/**
	 * Fire the listeners that were interested in this packet or its contents.
	 */
	public void fireListeners() {
		for (ListenerMethod method : interestedPacketListeners) {
			method.offer(packet);
		}

		if (packet instanceof ObjectUpdatePacket) {
			ObjectUpdatePacket ouPacket = (ObjectUpdatePacket) packet;

			for (ArtemisObject obj : ouPacket.getObjects()) {
				for (ListenerMethod method : interestedObjectListeners) {
					method.offer(obj);
				}
			}
		}
	}
}

@@ -3136,16 +3136,56 @@
 ers() %7B%0A
+%09%09if (packet == null) %7B%0A%09%09%09return;%0A%09%09%7D%0A%0A
 %09%09for (L

Fix fireListeners() barfing when there's no packet