PriceSortedIterator.java

package com.university.bookstore.iterator;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;

import com.university.bookstore.model.Material;

/**
 * Iterator that returns materials sorted by price.
 * Can sort in ascending or descending order.
 * 
 * @author Navid Mohaghegh
 * @version 3.0
 * @since 2024-09-15
 */
public class PriceSortedIterator implements MaterialIterator {
    
    private final List<Material> sortedMaterials;
    private int currentIndex;
    private final boolean ascending;
    
    /**
     * Creates a new price sorted iterator.
     * 
     * @param materials the list of materials to iterate over
     * @param ascending true for ascending order, false for descending
     */
    public PriceSortedIterator(List<Material> materials, boolean ascending) {
        this.sortedMaterials = new ArrayList<>(materials);
        this.ascending = ascending;
        this.currentIndex = 0;
        
        // Sort materials by price
        Comparator<Material> priceComparator = Comparator.comparing(Material::getPrice);
        if (!ascending) {
            priceComparator = priceComparator.reversed();
        }
        this.sortedMaterials.sort(priceComparator);
    }
    
    @Override
    public boolean hasNext() {
        return currentIndex < sortedMaterials.size();
    }
    
    @Override
    public Material next() {
        if (!hasNext()) {
            throw new NoSuchElementException("No more elements");
        }
        return sortedMaterials.get(currentIndex++);
    }
    
    @Override
    public void reset() {
        currentIndex = 0;
    }
    
    @Override
    public int getCurrentPosition() {
        return currentIndex;
    }
    
    @Override
    public int getTotalCount() {
        return sortedMaterials.size();
    }
    
    @Override
    public int getRemainingCount() {
        return sortedMaterials.size() - currentIndex;
    }
    
    @Override
    public boolean isAtBeginning() {
        return currentIndex == 0;
    }
    
    @Override
    public boolean isAtEnd() {
        return currentIndex >= sortedMaterials.size();
    }
    
    /**
     * Gets the sort order.
     * 
     * @return true if ascending, false if descending
     */
    public boolean isAscending() {
        return ascending;
    }
    
    /**
     * Gets the current material without advancing the iterator.
     * 
     * @return the current material
     * @throws NoSuchElementException if at the end
     */
    public Material peek() {
        if (currentIndex >= sortedMaterials.size()) {
            throw new NoSuchElementException("No more elements");
        }
        return sortedMaterials.get(currentIndex);
    }
    
    /**
     * Gets the next material without advancing the iterator.
     * 
     * @return the next material
     * @throws NoSuchElementException if no next element
     */
    public Material peekNext() {
        if (currentIndex + 1 >= sortedMaterials.size()) {
            throw new NoSuchElementException("No next element");
        }
        return sortedMaterials.get(currentIndex + 1);
    }
    
    @Override
    public String toString() {
        return String.format("PriceSortedIterator[Order=%s, Position=%d/%d]",
            ascending ? "ASC" : "DESC", getCurrentPosition(), getTotalCount());
    }
}