DigitalAnnotationDecorator.java
package com.university.bookstore.decorator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.university.bookstore.model.Material;
/**
* Decorator that adds digital annotation functionality to materials.
* Increases the price and provides annotation management capabilities.
*
* @author Navid Mohaghegh
* @version 3.0
* @since 2024-09-15
*/
public class DigitalAnnotationDecorator extends MaterialDecorator {
private static final double ANNOTATION_COST = 2.99;
private final List<String> annotations;
/**
* Creates a new digital annotation decorator.
*
* @param material the material to add annotations to
*/
public DigitalAnnotationDecorator(Material material) {
super(material);
this.annotations = new ArrayList<>();
}
@Override
public double getPrice() {
return decoratedMaterial.getPrice() + ANNOTATION_COST;
}
@Override
public String getDisplayInfo() {
return decoratedMaterial.getDisplayInfo() +
String.format(" [Digital Annotations: %d notes (+$%.2f)]",
annotations.size(), ANNOTATION_COST);
}
/**
* Adds an annotation to the material.
*
* @param annotation the annotation text
* @throws IllegalArgumentException if annotation is null or empty
*/
public void addAnnotation(String annotation) {
if (annotation == null || annotation.trim().isEmpty()) {
throw new IllegalArgumentException("Annotation cannot be null or empty");
}
annotations.add(annotation.trim());
}
/**
* Removes an annotation by index.
*
* @param index the index of the annotation to remove
* @return the removed annotation
* @throws IndexOutOfBoundsException if index is invalid
*/
public String removeAnnotation(int index) {
if (index < 0 || index >= annotations.size()) {
throw new IndexOutOfBoundsException("Invalid annotation index: " + index);
}
return annotations.remove(index);
}
/**
* Gets all annotations.
*
* @return unmodifiable list of annotations
*/
public List<String> getAnnotations() {
return Collections.unmodifiableList(annotations);
}
/**
* Gets the number of annotations.
*
* @return the annotation count
*/
public int getAnnotationCount() {
return annotations.size();
}
/**
* Clears all annotations.
*/
public void clearAnnotations() {
annotations.clear();
}
/**
* Gets the digital annotation cost.
*
* @return the annotation cost
*/
public double getDigitalAnnotationCost() {
return ANNOTATION_COST;
}
/**
* Checks if the material has any annotations.
*
* @return true if annotations exist
*/
public boolean hasAnnotations() {
return !annotations.isEmpty();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
if (!super.equals(obj)) return false;
DigitalAnnotationDecorator that = (DigitalAnnotationDecorator) obj;
return Objects.equals(annotations, that.annotations);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), annotations);
}
}