MaterialComponent.java

package com.university.bookstore.composite;

import java.util.List;

import com.university.bookstore.model.Material;

/**
 * Component interface for the Composite pattern.
 * 
 * <p>Represents both individual materials and composite bundles uniformly. The Composite Pattern is a structural design
 * pattern that allows developers to treat individual objects and groups of objects uniformly. This is particularly 
 * useful when working with tree-like structures, where both leaf objects (e.g., individual books) and composite 
 * objects (e.g., bundles of books) need to share the same interface.</p>
 * 
 * <p>The pattern promotes the principle of "compose objects into tree structures to represent part-whole hierarchies."
 * With Composite, clients can operate on single objects and entire compositions through a common interface,
 * simplifying the design and improving extensibility.</p>
 * 
 * <p>This interface allows clients to treat individual materials and material bundles uniformly, enabling 
 * recursive composition and polymorphic operations.</p>
 * 
 * <p>Example usage:</p>
 * <pre>{@code
 * MaterialComponent book = new MaterialLeaf(new PrintedBook(...));
 * MaterialComponent bundle = new MaterialBundle("Back-to-School Pack", 0.1);
 * bundle.addComponent(book);
 * 
 * // Both can be treated uniformly
 * double price = component.getPrice();
 * String info = component.getDisplayInfo();
 * }</pre>
 * 
 * @author Navid Mohaghegh
 * @version 3.0
 * @since 2024-09-15
 * @see MaterialLeaf
 * @see MaterialBundle
 * @see Material
 */
public interface MaterialComponent {
    
    /**
     * Gets the title of this component.
     * For individual materials, this is the material title.
     * For bundles, this is the bundle name.
     * 
     * @return the component title
     */
    String getTitle();
    
    /**
     * Gets the total price of this component.
     * For individual materials, this is the material price.
     * For bundles, this is the sum of all contained materials.
     * 
     * @return the total price
     */
    double getPrice();
    
    /**
     * Gets the discounted price of this component.
     * For individual materials, this applies the material's discount.
     * For bundles, this applies the bundle discount to the total price.
     * 
     * @return the discounted price
     */
    double getDiscountedPrice();
    
    /**
     * Gets a description of this component.
     * Provides detailed information about the component and its contents.
     * 
     * @return the component description
     */
    String getDescription();
    
    /**
     * Gets all materials contained in this component.
     * For individual materials, returns a list containing only itself.
     * For bundles, returns all materials in the bundle (recursively).
     * 
     * @return list of all contained materials
     */
    List<Material> getMaterials();
    
    /**
     * Gets the total number of items in this component.
     * For individual materials, returns 1.
     * For bundles, returns the sum of all contained items.
     * 
     * @return the total item count
     */
    int getItemCount();
    
    /**
     * Gets the discount rate applied to this component.
     * 
     * @return the discount rate (0.0 to 1.0)
     */
    double getDiscountRate();
    
    /**
     * Checks if this component is a leaf (individual material).
     * 
     * @return true if this is a leaf component
     */
    boolean isLeaf();
    
    /**
     * Checks if this component is a composite (bundle).
     * 
     * @return true if this is a composite component
     */
    default boolean isComposite() {
        return !isLeaf();
    }
}