public class Pizza {

    public static void main(String[] args){
	Auflagenart tomatensauce = new Auflagenart("Tomatensauce",0.0);
	Auflagenart schafskaese = new Auflagenart("Schafskaese",1.40);
	BasisPizzaart margherita = new BasisPizzaart("Margherita",4.40);
	margherita.addAuflagenart(tomatensauce);
	BasisPizzaart[] basisarten = new BasisPizzaart[1];
	basisarten[0] = margherita;
	Auflagenart[] auflagenarten = new Auflagenart[2];
	auflagenarten[0] = tomatensauce;
	auflagenarten[1] = schafskaese;
	Pizzaart meinePizza = new KomponiertePizzaart(margherita);
	meinePizza.addAuflagenart(schafskaese);
	System.out.println(meinePizza);
	System.out.println(meinePizza.getPreis());
    }
}

/**
   Eine Klasse, um etwas mit Namen und Preis abzuspeichern  
*/
abstract class Pizzaprodukt{
    
    private String name;
    private double preis;
    
    public void setName (String name){
	this.name = name;
    }
    public void setPreis (double preis){
	this.preis = preis;
    }
    public String getName(){  
	return name;
    }
    public double getPreis(){
	return preis;
    }
    public String toString(){// identisch mit getName()
	return name;
    }
}

class Auflagenart extends Pizzaprodukt{
    /** Der Konstruktor setzt alle Instanzvariablen der Oberklasse. */
    public Auflagenart(String name, double preis){
	setName(name);
	setPreis(preis);
    }
}

/**
   Eine Pizzaart ist im Wesentlichen ein Name, ein Preis und ein Array
   von Auflagenarten.
*/
abstract class Pizzaart extends Pizzaprodukt{

    public static final int MAX_AUFLAGENARTENZAHL = 50;
    private int naechsterIndex;
    private Auflagenart[] auflagenarten;

    public Pizzaart(){
	naechsterIndex = 0;
	auflagenarten = new Auflagenart[MAX_AUFLAGENARTENZAHL];
    }

    public int getAuflagenzahl(){
	return naechsterIndex;
    }

    public Auflagenart getAuflagenart(int index){
	if (0 <= index && index < naechsterIndex) return auflagenarten[index];
	else return null;
    }
    /**
       fügt Auflagenart hinzu, wenn noch nicht vorhanden
       und Array noch nicht besetzt ist
       @param auflagenart die hinzuzufügende Auflagenart
       @return ob die Auflagenart wirklich hinzugefügt wurde 
    */
    public boolean addAuflagenart(Auflagenart auflagenart){
	boolean gefunden = false;
	for (int i = 0; i < naechsterIndex; i++){
	    if (auflagenarten[i] == auflagenart) gefunden = true;
	}
		
	if (naechsterIndex < auflagenarten.length && !gefunden){
	    auflagenarten[naechsterIndex] = auflagenart;
	    naechsterIndex++;
	    return true;
	}
	else return false;
    }
    /**
       @return Kommaseparierte Liste aller Auflagennamen
    */
    public String alleAuflagen(){
	String ausgabe = "";
	for (int i = 0; i < naechsterIndex; i++){
	    if (i > 0) ausgabe = ausgabe + ", ";
	    ausgabe = ausgabe + auflagenarten[i].getName();
	}
	return ausgabe;
    }
}

class BasisPizzaart extends Pizzaart{
    // ist bis auf den Namen identisch mit Auflagenart

    public BasisPizzaart(String name, double preis){
	setName(name);
	setPreis(preis);
    }
}

/**
   Arten von Pizzas nach eigener Wahl
 */
class KomponiertePizzaart extends Pizzaart{

    private boolean erweitert;  // nur für Zwecke der Kommasetzung im Namen
    /**
       kopiert die Auflagenarten der Basispizza herein und ändert den Namen
       @param basis die Basispizza, die erweitert wird
     */
    public KomponiertePizzaart(BasisPizzaart basis){
	super();
	erweitert = false;
	for (int i = 0; i < basis.getAuflagenzahl(); i++){
	    super.addAuflagenart(basis.getAuflagenart(i));
	}
	setName(basis.getName()+" mit:");
	setPreis(basis.getPreis());
    }
    /**
       erweitert den Namen und erhöht auch den Preis
       @param auflagenart die hinzuzufügende Auflagenart
       @return ob die Auflagenart wirklich hinzugefügt wurde 
    */
    public boolean addAuflagenart(Auflagenart auflagenart){

	if (super.addAuflagenart(auflagenart)){
	    String neuerName = getName();
	    if (erweitert) neuerName = neuerName + ",";
	    setName(neuerName + " " + auflagenart.getName());
	    setPreis(getPreis() + auflagenart.getPreis());
	    erweitert = true;
	    return true;
	}
	else return false;
    }
}
