PriceChangedEvent.java
package com.university.bookstore.observer;
import java.util.Objects;
import com.university.bookstore.model.Material;
/**
* Event that occurs when a material's price changes.
*
* @author Navid Mohaghegh
* @version 3.0
* @since 2024-09-15
*/
public class PriceChangedEvent implements MaterialEvent {
private final Material material;
private final double oldPrice;
private final double newPrice;
private final long timestamp;
/**
* Creates a new price changed event.
*
* @param material the material whose price changed
* @param oldPrice the previous price
* @param newPrice the new price
* @throws IllegalArgumentException if material is null or prices are negative
*/
public PriceChangedEvent(Material material, double oldPrice, double newPrice) {
this.material = Objects.requireNonNull(material, "Material cannot be null");
if (oldPrice < 0) {
throw new IllegalArgumentException("Old price cannot be negative: " + oldPrice);
}
if (newPrice < 0) {
throw new IllegalArgumentException("New price cannot be negative: " + newPrice);
}
this.oldPrice = oldPrice;
this.newPrice = newPrice;
this.timestamp = System.currentTimeMillis();
}
@Override
public Material getMaterial() {
return material;
}
@Override
public long getTimestamp() {
return timestamp;
}
@Override
public String getEventType() {
return "PRICE_CHANGED";
}
@Override
public String getDescription() {
return String.format("Price changed for %s: $%.2f -> $%.2f (Change: $%.2f)",
material.getTitle(), oldPrice, newPrice, newPrice - oldPrice);
}
/**
* Gets the old price.
*
* @return the previous price
*/
public double getOldPrice() {
return oldPrice;
}
/**
* Gets the new price.
*
* @return the new price
*/
public double getNewPrice() {
return newPrice;
}
/**
* Gets the price change amount.
*
* @return the price change (new - old)
*/
public double getPriceChange() {
return newPrice - oldPrice;
}
/**
* Gets the price change percentage.
*
* @return the price change percentage
*/
public double getPriceChangePercentage() {
if (oldPrice == 0) {
return newPrice > 0 ? 100.0 : 0.0;
}
return ((newPrice - oldPrice) / oldPrice) * 100.0;
}
/**
* Checks if the price increased.
*
* @return true if the price increased
*/
public boolean isPriceIncrease() {
return newPrice > oldPrice;
}
/**
* Checks if the price decreased.
*
* @return true if the price decreased
*/
public boolean isPriceDecrease() {
return newPrice < oldPrice;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
PriceChangedEvent that = (PriceChangedEvent) obj;
return Double.compare(that.oldPrice, oldPrice) == 0 &&
Double.compare(that.newPrice, newPrice) == 0 &&
timestamp == that.timestamp &&
Objects.equals(material, that.material);
}
@Override
public int hashCode() {
return Objects.hash(material, oldPrice, newPrice, timestamp);
}
@Override
public String toString() {
return String.format("PriceChangedEvent[%s: $%.2f -> $%.2f at %d]",
material.getTitle(), oldPrice, newPrice, timestamp);
}
}