package com.nicewuerfel.blockown.database; import com.nicewuerfel.blockown.Ownable; import com.nicewuerfel.blockown.User; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * Immutable object which represents a single action to be performed on the owning database. * * @author Pheasn */ public final class DatabaseAction { @Nullable private final User user; @Nullable private final Ownable ownable; @Nonnull private final Type type; private final long timeStamp; private final int hashCode; private int attempts = 0; /** * The type of a {@link DatabaseAction}. */ public enum Type { /** * Drop all ownings of a {@link User} from the database. */ DROP, /** * Own a {@link Ownable} for a {@link User}. */ OWN, /** * Delete the owner of a {@link Ownable}. */ UNOWN } /** * Instantiated a new DatabaseAction of the {@link Type} {@link Type#UNOWN UNOWN}. * * @param ownable the Ownable to unown * @return the {@link DatabaseAction} */ @Nonnull public static DatabaseAction newUnownInstance(@Nonnull Ownable ownable) { return new DatabaseAction(Type.UNOWN, Objects.requireNonNull(ownable), null); } @Nonnull public static DatabaseAction newOwnInstance(@Nonnull Ownable ownable, @Nonnull User user) { return new DatabaseAction(Type.OWN, Objects.requireNonNull(ownable), Objects.requireNonNull(user)); } @Nonnull public static DatabaseAction newDropInstance(@Nonnull User user) { return new DatabaseAction(Type.DROP, null, Objects.requireNonNull(user)); } /** * Instantiates a new DatabaseAction. * * @param type the DatabaseActionType * @param ownable the ownable, may be null if type is DROP * @param user the user, may be null if type is UNOWN */ private DatabaseAction(@Nonnull Type type, @Nullable Ownable ownable, @Nullable User user) { this.user = user; this.ownable = ownable; this.type = type; this.timeStamp = System.currentTimeMillis(); this.hashCode = calcHashCode(); } @Nullable public User getUser() { return user; } @Nullable public Ownable getOwnable() { return ownable; } public long getTimeStamp() { return timeStamp; } @Nonnull public Type getActionType() { return type; } /** * Adds an attempt to the counter and returns the count before the attempt. * * @return the attempt count before this call. */ int addAttempt() { return attempts++; } int getAttempts() { return attempts; } private int calcHashCode() { final int prime = 31; int result = 3; result = prime * result + type.hashCode(); result = prime * result + ((ownable == null) ? 0 : ownable.hashCode()); result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32)); result = prime * result + ((user == null) ? 0 : user.hashCode()); return result; } @Override public int hashCode() { return hashCode; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof DatabaseAction)) { return false; } DatabaseAction other = (DatabaseAction) obj; if (type != other.type) { return false; } if (ownable == null) { if (other.ownable != null) { return false; } } else if (!ownable.equals(other.ownable)) { return false; } if (Long.compare(timeStamp, other.timeStamp) != 0) { return false; } if (user == null) { if (other.user != null) { return false; } } else if (!user.equals(other.user)) { return false; } return true; } @Override public String toString() { return "DatabaseAction [user=" + user + ", ownable=" + ownable + ", type=" + type + ", timeStamp=" + new SimpleDateFormat().format(new Date(timeStamp)) + "]"; } }