/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.dlect.events; import com.google.common.base.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; import static org.dlect.helper.Conditions.checkNonNull; /** * * @author lee */ public class Event { @Nonnull private final Object source; @Nonnull private final EventID eventID; @Nullable private final Object before; @Nullable private final Object after; /** * Creates a new event with the given source, eventID, before and after states. * * @param source A non-null source that is assignable from the given {@code eventID}'s * {@link EventID#getAppliedClass()}. * @param eventID A non-null eventID that must represent an event that is applied to a super-type of the given * {@code source}. * @param before The state before the change. This object is not checked for equality with {@code after}; or * null-ness. It is recommended that this object be immutable as no copy is made. * @param after The state after the change. This object is not checked for equality with {@code before}; or * null-ness. It is recommended that this object be immutable as no copy is made. */ public Event(@Nonnull Object source, @Nonnull EventID eventID, @Nullable Object before, @Nullable Object after) { checkNonNull(source, "Source"); checkNonNull(eventID, "Event ID"); if (!eventID.getAppliedClass().isAssignableFrom(source.getClass())) { // If the event ID represents a supertype of or equal to source class; then good. Otherwise error. throw new IllegalArgumentException("Source(" + source.getClass() + ") is not a sub-type of the class that the event ID(" + eventID.getAppliedClass() + ") applies to."); } this.source = source; this.eventID = eventID; this.before = before; this.after = after; } public String debugVars() { return "source=" + source + ", eventID=" + eventID + ", before=" + before + ", after=" + after; } @Override public String toString() { return "Event{" + debugVars() + '}'; } @Override public int hashCode() { return Objects.hashCode(this.getSource(), this.getEventID(), this.getBefore(), this.getAfter()); } @Override public boolean equals(Object obj) { if (obj != null && obj.getClass().equals(this.getClass())) { final Event other = (Event) obj; return equalsImpl(other); } else { return false; } } /** * Perform an implementer independent equality check. This method will only check for equality with the elements of * this class. This method does not perform any type checking and is safe to use in an implementation to check if * the root event is equal. * * This method will check equality on {@link #getBefore()}, {@link #getAfter()}, {@link #getEventID()}, and * {@link #getSource()} * * @param other The event to check equality on. * * @return {@code true} if this event has the same event data as {@code other}. Otherwise {@code false} */ protected final boolean equalsImpl(Event other) { return Objects.equal(this.getSource(), other.getSource()) && Objects.equal(this.getEventID(), other.getEventID()) && Objects.equal(this.getBefore(), other.getBefore()) && Objects.equal(this.getAfter(), other.getAfter()); } /** * The source class that this event represents. This is generated by calling {@link EventID#getAppliedClass() }. * * @return The source class that this event represents. */ @Nonnull public Class<?> getSourceClass() { return eventID.getAppliedClass(); } /** * The source object of this event. Note that this source is guaranteed to be castable to, but not necessarily the * same as, the class returned by {@link #getSourceClass()} * * @return The source of the object. */ @Nonnull public Object getSource() { return source; } /** * The ID of the event. * * @return The ID of event. */ @Nonnull public EventID getEventID() { return eventID; } /** * The object before it was changed.This may be equal to {@link #getAfter() }; this class makes no assumptions on * this. * * @return The object before it was changed. */ @Nullable public Object getBefore() { return before; } /** * The object after the change. This may be equal to {@link #getBefore() }; this class makes no assumptions on this. * * @return The object after the change. */ @Nullable public Object getAfter() { return after; } }