1.5 🚧 Projekt Medienverwaltung

Bei diesem Unterrichtsentwurf sollen die OOP-Grundlagen aus der TGI-Eingangsklasse oder dem 1. Lehrjahr Fachinformatiker wiederholt und erweitert werden.

Synopsis: Zeichensoftware: umlet.com Anleitung: UMLet_Kurzanleitung_eck-2017.pdf

  1. Zusicherungen umsetzen: Einfache Büchersammlung mit wenigen exemplarischen Attributen erstellen, dabei simple Arrays verwenden. Zusicherungen finden und umsetzen, zunächst mit simplen Konsolenmeldungen bei Verletzungen.
  2. Exceptions verwenden: Methode einfuegenBuch(..) der Klasse Buechersammlung müsste die Zusicherungen der Attribute der Klasse Buch bereits überprüfen, damit erst gar kein “falsches” Buch erzeugt werden kann. Doppelter Code ist doof. Lösung: Exceptions statt Konsolenmeldungen.
  3. Dynamische Listen: ArrayList statt Array verwenden, Sortieren, Vorteile sortierter Listen, sortiertes Einfügen..
  4. Speichern und Laden: Als CSV, XML, JSON
  5. Abstrakte Klasse: Zur Mediensammlung erweitern
  6. Speichern und Laden an neue Datenstruktur anpassen
  7. Oberfläche dazu: 3-Schichten Architektur. TGI: Sequenzdiagramm..

1. Einfache Büchersammlung mit Zusicherungen

Für eine Büchersammlung soll eine Software erstellt werden. Hier ein (unvollständiger) Entwurf eines Klassendiagramms und ein wenig Java-Code.
Die Überprüfung von Zusicherungen z.B. {>=0} dienen dazu fehlerhafte Attributswerte frühzeitig zu erkennen und Denkfehler bei der Implementierung zu vermeiden.
Zusicherungen werden in den Klassen überprüft, die die Attributswerte setzen.

Klassendiagramm Vorgabe
Klassendiagramm Vorgabe
OperationBeschreibung
einfuegenGenre(name:Text):GenreDurchsucht das ganze unsortierte Feld dasGenre[] nach einem Genre-Objekt mit dem Namen name. Falls es existiert wird eine neues Objekt erzeugt und eingefügt. Rückgabe ist die ID des Genre-Objekts.
einfuegenBuch(titel:Text,preis:FKZ,seiten:GZ,genre:Text)Erzeugt ein neues Buch und fügt es in das Feld ein.
getAnzahlBuecher():GZGibt die Anzahl der gespeicherten Bücher in der Sammlung zurück.
getAnzahlGenre():GZGibt die Anzahl der Genres zurück.
ausgebenGenre()Gibt eine Liste aller Genres auf der Konsole aus
ausgebenSammlung()Gibt eine Liste aller Bücher auf der Konsole aus, verwendet Buch.ausgebenInfo()
Klasse Buechersammlung Operationen
OperationBeschreibung
Genre(name:Text)Erzeugt ein neues Genre-Objekt
getName():TextGibt den Namen des Genres zurück
Klasse Genre Operationen
OperationBeschreibung
Buch(titel:Text,preis:FKZ,seiten:GZ,genre:Genre)Erzeugt ein neues Buch-Objekt
ausgebenInfo()Gibt die Buchinfos formatiert auf der Konsole aus. [printf()]
Klasse Buch Operationen

Codevorgaben

public class Test{
  private static Buechersammlung dieBuechersammlung = new Buechersammlung();
  public static void testen(){
    System.out.print("\f"); // Konsole löschen
    // Buch testen
    //Buch testBuch = new Buch(null,-12.3,-33,null);
    //testBuch.ausgebenInfo();
    dieBuechersammlung.einfuegenGenre("Herzschmerz");
    //dieBuechersammlung.einfuegenGenre("");
    dieBuechersammlung.einfuegenGenre("Thriller");
    dieBuechersammlung.ausgebenGenre();
    dieBuechersammlung.einfuegenBuch("Wunderbare Welt2",10,66,"Schwurbel");
    dieBuechersammlung.einfuegenBuch("Nasen",2,100,"");
    dieBuechersammlung.einfuegenBuch("Buben",-2,100,"Gaga");
    dieBuechersammlung.einfuegenBuch("Die Leiden des jungen Werthers",2,100,"Sturm und Drang");
    dieBuechersammlung.ausgebenGenre();
    dieBuechersammlung.ausgebenSammlung();
  }
}
public class Buechersammlung{
  public static final int MAX_ANZAHL=10;
  private int anzahlBuecher;
  private int anzahlGenre;
  private Genre dasGenre[] = new Genre[MAX_ANZAHL];
  private Buch dasBuch[] = new Buch[MAX_ANZAHL];
  public Genre einfuegenGenre(String name){ // gibt ID des Genre-Objekts zurück
    if(name==null || name.equals("")){
      System.out.println("Buechersammlung.einfuegenGenre(): Genre leer");
      return null;
    }
    for(int i=0;i<anzahlGenre;i++){      // schon vorhanden?
      if(name.equals(dasGenre[i].getName())){
        return dasGenre[i]; 
      }
    }
    if(anzahlGenre>=MAX_ANZAHL){  // ist noch Platz?
      System.out.println("Buechersammlung.einfuegenGenre(): Kein Platz für neues Genre");
      return null;
    }
    Genre g=new Genre(name);
    dasGenre[anzahlGenre++]=g; // g einfügen und anzahlGenre erhöhen
    return g;
  }
  public void einfuegenBuch(String titel,double preis,int seiten,String genre){
    if (titel==null || titel.equals("")){
      System.out.println("Buechersammlung.einfuegenBuch(): Kein Titel");
      return;
    }  
    if (preis<0.0){
      System.out.println("Buechersammlung.einfuegenBuch(): Preis negativ");
      return;
    }
    if (seiten<0){
      System.out.println("Buechersammlung.einfuegenBuch(): Seitenanzahl negativ");
      return;
    }
    if (genre==null || genre.equals("")){
      System.out.println("Buechersammlung.einfuegenBuch(): Kein Genre");
      return;
    }
    if(anzahlBuecher>=MAX_ANZAHL){
      System.out.println("Buechersammlung.einfuegenBuch(): Kein Platz für neue Bücher");
      return;
    }
    Genre g = einfuegenGenre(genre);
    if(g==null){
      System.out.println("Buechersammlung.einfuegenBuch(): Kein Platz für weiteres Genre");
      return;
    }
    dasBuch[anzahlBuecher++] = new Buch(titel,preis,seiten,g); // neues Buch einfügen
  }
  public int getAnzahlBuecher(){
    return anzahlBuecher;
  }
  public void ausgebenGenre(){
    System.out.println("Buechersammlung.ausgebenGenre():");
    for(int i=0;i<anzahlGenre;i++){
      System.out.printf("%2d. %s\n",i,dasGenre[i].getName());
    }
  }
  public void ausgebenSammlung(){
    System.out.println("Buechersammlung.ausgebenSammlung():");
    for(int i=0;i<anzahlBuecher;i++){
      dasBuch[i].ausgebenInfo();
    }
  }
}
public class Genre{
  private String name; // {nicht leer}
  public Genre(String name){
    if (name==null || name.equals("")){
      System.out.println("Genre: Name leer");
      this.name = "Name leer";
    } else {
      this.name=name; 
    }   
  }
  public String getName(){
    return name;
  }
}
public class Buch{
  private String titel;   // {nicht leer}
  private double preis;   // {>=0.0}
  private int seiten;     // {>=0}
  private Genre dasGenre; // {nicht null}
  public Buch(String titel,double preis,int seiten,Genre genre){
    if (titel==null || titel.equals("")){
      this.titel = "Kein Titel";
      System.out.println("Buch: Kein Titel");    
    } else {
      this.titel = titel; 
    }
    if (preis<0.0){
      System.out.println("Buch: Preis negativ");  
    } else {
      this.preis = preis;
    }
    if (seiten<0){
      System.out.println("Buch: Seitenanzahl negativ");  
    } else {
      this.seiten = seiten; 
    }
    if (genre==null){
      System.out.println("Buch: Genre null");
    }
    dasGenre = genre;
  }
  public void ausgebenInfo(){
    System.out.printf("Titel: %-30s \tPreis:%7.2f€ \tSeiten:%5d \tGenre: %s\n",titel,preis,seiten,dasGenre.getName());
  }
}

Aufgaben für Fachinformatiker

Für Struktogramme verwenden Sie [structorizer.fisch.lu].

  1. Erstellen Sie Struktogramm für Buechersammlung.ausgebenGenre()
  2. Erstellen Sie Struktogramm für Genre(name:Text)
1. Lösungsvorschlag Buechersammlung.ausgebenGenre()
Struktogramm
2. Lösungsvorschlag Genre(name:Text)
Struktogramm

2. Exceptions verwenden

Die Methode einfuegenBuch(..) der Klasse Buechersammlung musste die Zusicherungen der Attribute der Klasse Buch bereits überprüfen, damit erst gar kein “falsches” Buch erzeugt werden kann. Doppelter Code ist doof. Lösung: Exceptions statt Konsolenmeldungen.

public class Buechersammlung{
  public static final int MAX_ANZAHL=10;
  private int anzahlBuecher;
  private int anzahlGenre;
  private Genre dasGenre[] = new Genre[MAX_ANZAHL];
  private Buch dasBuch[] = new Buch[MAX_ANZAHL];
  public Genre einfuegenGenre(String name){ // gibt ID des Genre-Objekts zurück
    if(name==null || name.equals("")){
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Genre leer");  
    }
    for(int i=0;i<anzahlGenre;i++){      // schon vorhanden?
      if(name.equals(dasGenre[i].getName())){
        return dasGenre[i]; 
      }
    }
    if(anzahlGenre>=MAX_ANZAHL){  // ist noch Platz?
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Kein Platz für neues Genre");  
    }
    Genre g=new Genre(name);
    dasGenre[anzahlGenre++]=g; // g einfügen und anzahlGenre erhöhen
    return g;
  }
  public void einfuegenBuch(String titel,double preis,int seiten,String genre){
    if(anzahlBuecher>=MAX_ANZAHL){
      System.out.println("Buechersammlung.einfuegenBuch(): Kein Platz für neue Bücher");
      return;
    }
    try {
      Genre g = einfuegenGenre(genre);
      try {
       Buch b =new Buch(titel,preis,seiten,g); // neues Buch einfügen
       dasBuch[anzahlBuecher++] = b;
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public int getAnzahlBuecher(){
    return anzahlBuecher;
  }
  public void ausgebenGenre(){
    System.out.println("Buechersammlung.ausgebenGenre():");
    for(int i=0;i<anzahlGenre;i++){
      System.out.printf("%2d. %s\n",i,dasGenre[i].getName());
    }
  }
  public void ausgebenSammlung(){
    System.out.println("Buechersammlung.ausgebenSammlung():");
    for(int i=0;i<anzahlBuecher;i++){
      dasBuch[i].ausgebenInfo();
    }
  }
}
public class Genre{
  private String name; // {nicht leer}
  public Genre(String name){
    if (name==null || name.equals("")){
      throw new IllegalArgumentException("Genre: Name leer");  
    }
    this.name=name; 
  }
  public String getName(){
    return name;
  }
}
public class Buch{
  private String titel;   // {nicht leer}
  private double preis;   // {>=0.0}
  private int seiten;     // {>=0}
  private Genre dasGenre; // {nicht null}
  public Buch(String titel,double preis,int seiten,Genre genre){
    if (titel==null || titel.equals("")){
      throw new IllegalArgumentException("Buch: Kein Titel");
    }
    this.titel = titel;
    if (preis<0.0){
      throw new IllegalArgumentException("Buch: Preis negativ");  
    }
    this.preis = preis;
    if (seiten<0){
      throw new IllegalArgumentException("Buch: Seitenanzahl negativ"); 
    }
    this.seiten = seiten; 
    if (genre==null){
      throw new IllegalArgumentException("Buch: Genre null"); 
    }
    dasGenre = genre;
  }
  public void ausgebenInfo(){
    System.out.printf("Titel: %-30s \tPreis:%7.2f€ \tSeiten:%5d \tGenre: %s\n",titel,preis,seiten,dasGenre.getName());
  }
}

3. Dynamische Listen

Die Begrenzung auf MAX_ANZAHL=10 Einträge lässt sich durch dynamische Listen überwinden. ArrayList: [🔗 docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html]
Ausserdem können die Ausgaben sortiert werden: –nachPreis –nachSeiten usw..

// Buecherverwaltung-Ex-Liste v1.0
public class Test{
  private static Buechersammlung dieBuechersammlung = new Buechersammlung();
  public static void testen(){
    System.out.print("\f"); // Konsole löschen
    // Buch testen
    //Buch testBuch = new Buch(null,-12.3,-33,null);
    //testBuch.ausgebenInfo();
    dieBuechersammlung.einfuegenGenre("Herzschmerz");
    //dieBuechersammlung.einfuegenGenre("");
    dieBuechersammlung.einfuegenGenre("Thriller");
    dieBuechersammlung.ausgebenGenre();
    dieBuechersammlung.einfuegenBuch("Wunderbare Welt",10,66,"Schwurbel");
    dieBuechersammlung.einfuegenBuch("Nasen",2,100,"");
    dieBuechersammlung.einfuegenBuch("Informatik für Dummys",15.95,238,"Lehrbuch");
    dieBuechersammlung.einfuegenBuch("Die Leiden des jungen Werthers",7.80,100,"Sturm und Drang");
    dieBuechersammlung.ausgebenGenre();
    dieBuechersammlung.ausgebenSammlung();
    dieBuechersammlung.sortierePreis();
    dieBuechersammlung.ausgebenSammlung();
    dieBuechersammlung.sortiereSeiten();
    dieBuechersammlung.ausgebenSammlung();
    dieBuechersammlung.sortiereGenre();
    dieBuechersammlung.ausgebenGenre();
    dieBuechersammlung.sortiereGenreRev();
    dieBuechersammlung.ausgebenGenre();
  }
}
// Buecherverwaltung-Ex-Liste v1.0
import java.util.ArrayList;
public class Buechersammlung{
  private ArrayList<Genre> dasGenre = new ArrayList<Genre>();
  private ArrayList<Buch> dasBuch = new ArrayList<Buch>();
  public Genre einfuegenGenre(String name){ // gibt ID des Genre-Objekts zurück
    if(name==null || name.equals("")){
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Genre leer");  
    }
    for(int i=0;i<dasGenre.size();i++){      // schon vorhanden?
      if(name.equals(dasGenre.get(i).getName())){
        return dasGenre.get(i); 
      }
    }
    Genre g=new Genre(name);
    dasGenre.add(g); // g einfügen
    return g;
  }
  public void einfuegenBuch(String titel,double preis,int seiten,String genre){
    try {
      Genre g = einfuegenGenre(genre);
      try {
       Buch b =new Buch(titel,preis,seiten,g); // neues Buch einfügen
       dasBuch.add(b);
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public int getAnzahlBuecher(){
    return dasBuch.size();
  }
  public void ausgebenGenre(){
    System.out.println("Buechersammlung.ausgebenGenre():");
    for(int i=0;i<dasGenre.size();i++){
      System.out.printf("%2d. %s\n",i,dasGenre.get(i).getName());
    }
  }
  public void ausgebenSammlung(){
    System.out.println("Buechersammlung.ausgebenSammlung():");
    for(int i=0;i<dasBuch.size();i++){
      System.out.printf("%3d. ",i+1);
      dasBuch.get(i).ausgebenInfo();
    }
  }
  public void sortierePreis(){
    dasBuch.sort((a,b)->{return a.comparePreis(b);}); // Lambda Ausdruck für sort()
  }
  public void sortiereSeiten(){
    dasBuch.sort((a,b)->{return a.compareSeiten(b);});
  }
  public void sortiereGenre(){
    dasGenre.sort((a,b)->{return a.compareName(b);});
  }
  public void sortiereGenreRev(){ // String hat Comparable implementiert
    dasGenre.sort((a,b)->{return -1*a.getName().compareTo(b.getName());});
  }
}
// Buecherverwaltung-Ex-Liste v1.0
public class Genre{
  private String name; // {nicht leer}
  public Genre(String name){
    if (name==null || name.equals("")){
      throw new IllegalArgumentException("Genre: Name leer");  
    }
    this.name=name; 
  }
  public String getName(){
    return name;
  }
  public int compareName(Genre g){ // Metrik für aufsteigende Sortierung
    return name.compareTo(g.name);
  }
}
// Buecherverwaltung-Ex-Liste v1.0
public class Buch{
  private String titel;   // {nicht leer}
  private double preis;   // {>=0.0}
  private int seiten;     // {>=0}
  private Genre dasGenre; // {nicht null}
  public Buch(String titel,double preis,int seiten,Genre genre){
    if (titel==null || titel.equals("")){
      throw new IllegalArgumentException("Buch: Kein Titel");
    }
    this.titel = titel;
    if (preis<0.0){
      throw new IllegalArgumentException("Buch: Preis negativ");  
    }
    this.preis = preis;
    if (seiten<0){
      throw new IllegalArgumentException("Buch: Seitenanzahl negativ"); 
    }
    this.seiten = seiten; 
    if (genre==null){
      throw new IllegalArgumentException("Buch: Genre null"); 
    }
    dasGenre = genre;
  }
  public double getPreis(){
    return preis;
  }
  public void ausgebenInfo(){
    System.out.printf("Titel: %-30s \tPreis:%7.2f€ \tSeiten:%5d \tGenre: %s\n",titel,preis,seiten,dasGenre.getName());
  }
  public int comparePreis(Buch b){ // Metrik für aufsteigende Sortierung
    if(preis==b.preis) return 0;
    if(preis>b.preis) return 1;
    return -1;
  }
  public int compareSeiten(Buch b){ // Metrik für aufsteigende Sortierung
    if(seiten==b.seiten) return 0;
    if(seiten>b.seiten) return 1;
    return -1;
  }
}

🖌 Erstellen Sie ein Klassendiagramm für die Lösung mit den dynamischen Listen.

Lösung

Sortiertes Einfügen eines Genres

Synopsis: [https://mezdata.de/pi-bluej/140_listen/index.php] ArrayList: [🔗 docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html]

🍀 @Raa: Erstellen Sie eine Methode Buecherverwaltung.einfuegenGenreSort(name:Text), die neue Genres gleich sortiert eingefügt werden, verwenden Sie dabei name.compareTo(dasGenre.get(i).getName()) und dasGenre.add(i:GZ,g:Genre); // an Position i einfügen

Lösungsvorschlag
  public Genre einfuegenGenreSort(String name){ // gibt ID des Genre-Objekts zurück
    int i;  
    if(name==null || name.equals("")){
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Genre leer");  
    }
    for(i=0;i<dasGenre.size();i++){ // Liste durchgehen
      if(name.equals(dasGenre.get(i).getName())){      // schon vorhanden?
        return dasGenre.get(i); 
      }
      if(name.compareTo(dasGenre.get(i).getName())<1){ // kommt nicht mehr
        Genre g=new Genre(name);
        dasGenre.add(i,g); // an Position i einfügen
        return g;
      }
    }
    Genre g=new Genre(name); // am Ende einfügen
    dasGenre.add(g); // g einfügen
    return g;
  }

4. Speichern und Laden

Synopsis: [https://mezdata.de/pi-bluej/125_passwort-projekt/index.php]

// Buechersammlung ergänzen
  import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.*; // Pfad-Klasse
...
public void schreibeCSV(String dateiname){
  int i;
  Path pfad = Paths.get(dateiname); // Dateipfad
  try {  // versuchen wir mal folgenden Code aus zu fuehren
    Writer aus = Files.newBufferedWriter(pfad); //Datenschreiber
    for(i=0;i<getAnzahlBuecher();i++){
      aus.write(dasBuch.get(i).toCSV()+"\n"); //schreibe
    }
    aus.close(); // schliesse Datenstrom
  } catch (IOException e) {  //falls ein IO-Ausnahmefehler
    System.out.println("IOException: " + e);  //Fehler ausgeben
  }
}
// Buch ergänzen
public String toCSV(){
  return String.format("%s;%.2f;%d;%s",titel,preis,seiten,dasGenre.getName());
}
  public void leseCSV(String dateiname){
    int i;
    Path pfad = Paths.get(dateiname); // Dateipfad
    String zeile;
    String[] attribute;
    try { // versuchen wir mal folgenden Code aus zu fuehren
      BufferedReader ein = Files.newBufferedReader(pfad); // oeffne Datenstrom
      while ((zeile = ein.readLine())!= null){ // solange Datensaetze vorhanden, lese Zeile
        zeile=zeile.replace(',','.'); // damit Doubleparsen geht
        attribute = zeile.split(";");
        einfuegenBuch(attribute[0],Double.parseDouble(attribute[1]),Integer.parseInt(attribute[2]),attribute[3]);
      }
      ein.close(); // schliesse Datenstrom
    } catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
      System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
    }
  }

ToDo: XML und JSON

Erweitern zur Medienverwaltung

Nun sollen auch DVDs verwaltet werden können, hier ein Entwurf für die Erweiterung:

Klassendiagramm Medienverwaltung
Klassendiagramm Medienverwaltung

Führen Sie eine Generalisierung der Klassen Buch und DVD zu einer Oberklasse Medium durch, welche Operationen müssen als abstrakt gekennzeichnet werden?

Lösungsvorschlag
Klassendiagramm noch Generalisierung
Klassendiagramm noch Generalisierung

Erstellen Sie den Quellcode für das Programm…

Lösungsvorschlag Test.java
// Medienverwaltung-Ex-Liste v1.0
public class Test{

  public static void main(String[] args) {
    testen();
  }
  private static Medienverwaltung dieMedienverwaltung = new Medienverwaltung();
  public static void testen(){
    System.out.print("\f"); // Konsole löschen
    // Buch testen
    //Buch testBuch = new Buch(null,-12.3,-33,null);
    //testBuch.ausgebenInfo();
    dieMedienverwaltung.einfuegenGenre("Herzschmerz");
    //dieMedienverwaltung.einfuegenGenre("");
    dieMedienverwaltung.einfuegenGenre("Thriller");
    dieMedienverwaltung.ausgebenGenre();
    dieMedienverwaltung.einfuegenBuch("Wunderbare Welt",10,66,"Schwurbel");
    dieMedienverwaltung.einfuegenBuch("Nasen",2,100,"");
    dieMedienverwaltung.einfuegenBuch("Informatik für Dummys",15.95,238,"Lehrbuch");
    dieMedienverwaltung.einfuegenBuch("Die Leiden des jungen Werthers",7.80,100,"Sturm und Drang");
    dieMedienverwaltung.einfuegenDVD("Dark Star",10.50,123,"Sience Fiction");
    dieMedienverwaltung.einfuegenDVD("Die kalten Gedanken",9.95,187,"Horror");
    dieMedienverwaltung.ausgebenGenre();
    dieMedienverwaltung.ausgebenSammlung();
    System.out.println("Schreiben und Lesen");
    dieMedienverwaltung.schreibeCSV("Medien.csv");
    dieMedienverwaltung.leseCSV("Medien.csv");
    dieMedienverwaltung.ausgebenSammlung();
  }
}
Lösungsvorschlag
// Medienverwaltung-Ex-Liste v1.0
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.*; // Pfad-Klasse

public class Medienverwaltung{
  private ArrayList<Genre> dasGenre = new ArrayList<Genre>();
  private ArrayList<Medium> dasMedium = new ArrayList<Medium>();
  public Genre einfuegenGenre(String name){ // gibt ID des Genre-Objekts zurück
    int i;  
    if(name==null || name.equals("")){
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Genre leer");  
    }
    for(i=0;i<dasGenre.size();i++){ // Liste durchgehen
      if(name.equals(dasGenre.get(i).getName())){      // schon vorhanden?
        return dasGenre.get(i); 
      }
      if(name.compareTo(dasGenre.get(i).getName())<1){ // kommt nicht mehr
        Genre g=new Genre(name);
        dasGenre.add(i,g); // an Position i einfügen
        return g;
      }
    }
    Genre g=new Genre(name); // am Ende einfügen
    dasGenre.add(g); // g einfügen
    return g;
  }
  public void einfuegenBuch(String titel,double preis,int seiten,String genre){
    try {
      Genre g = einfuegenGenre(genre);
      try {
       Buch b =new Buch(titel,preis,seiten,g); // neues Buch einfügen
       dasMedium.add(b);
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public void einfuegenDVD(String titel,double preis,int dauer,String genre){
    try {
      Genre g = einfuegenGenre(genre);
      try {
       DVD d =new DVD(titel,preis,dauer,g); // neues Buch einfügen
       dasMedium.add(d);
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public int getAnzahlBuecher(){
    return dasMedium.size();
  }
  public void ausgebenGenre(){
    System.out.println("Buechersammlung.ausgebenGenre():");
    for(int i=0;i<dasGenre.size();i++){
      System.out.printf("%2d. %s\n",i,dasGenre.get(i).getName());
    }
  }
  public void ausgebenSammlung(){
    System.out.println("Buechersammlung.ausgebenSammlung():");
    for(int i=0;i<dasMedium.size();i++){
      System.out.printf("%3d. ",i+1);
      dasMedium.get(i).ausgebenInfo();
    }
  }
  public void sortierePreis(){
    dasMedium.sort((a,b)->{return a.comparePreis(b);}); // Lambda Ausdruck für sort()
  }
  /*public void sortiereSeiten(){
    dasBuch.sort((a,b)->{return a.compareSeiten(b);});
  }*/
  public void sortiereGenre(){
    dasGenre.sort((a,b)->{return a.compareName(b);});
  }
  public void sortiereGenreRev(){ // String hat Comparable implementiert
    dasGenre.sort((a,b)->{return -1*a.getName().compareTo(b.getName());});
  }
  public void leseCSV(String dateiname){
    int i;
    Path pfad = Paths.get(dateiname); // Dateipfad
    String zeile;
    String[] attribute;
    try { // versuchen wir mal folgenden Code aus zu fuehren
      BufferedReader ein = Files.newBufferedReader(pfad); // oeffne Datenstrom
      while ((zeile = ein.readLine())!= null){ // solange Datensaetze vorhanden, lese Zeile
        zeile=zeile.replace(',','.'); // damit Doubleparsen geht
        attribute = zeile.split(";");
        if(attribute[0].equals("Buch")){
          einfuegenBuch(attribute[1],Double.parseDouble(attribute[2]),Integer.parseInt(attribute[3]),attribute[4]);  
        }
        else if (attribute[0].equals("DVD")){
          einfuegenDVD(attribute[1],Double.parseDouble(attribute[2]),Integer.parseInt(attribute[3]),attribute[4]);  
        }
      }
      ein.close(); // schliesse Datenstrom
    } catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
      System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
    }
  }
  public void schreibeCSV(String dateiname){
    int i;
    Path pfad = Paths.get(dateiname); // Dateipfad
    try {  // versuchen wir mal folgenden Code aus zu fuehren
      Writer aus = Files.newBufferedWriter(pfad); //Datenschreiber
      for(i=0;i<getAnzahlBuecher();i++){
        aus.write(dasMedium.get(i).toCSV()+"\n"); //schreibe
      }
      aus.close(); // schliesse Datenstrom
    } catch (IOException e) {  //falls ein IO-Ausnahmefehler
      System.out.println("IOException: " + e);  //Fehler ausgeben
    }
  }
}
// Medienverwaltung-Ex-Liste v1.0
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.*; // Pfad-Klasse

public class Medienverwaltung{
  private ArrayList<Genre> dasGenre = new ArrayList<Genre>();
  private ArrayList<Medium> dasMedium = new ArrayList<Medium>();
  public Genre einfuegenGenre(String name){ // gibt ID des Genre-Objekts zurück
    int i;  
    if(name==null || name.equals("")){
      throw new IllegalArgumentException("Buechersammlung.einfuegenGenre(): Genre leer");  
    }
    for(i=0;i<dasGenre.size();i++){ // Liste durchgehen
      if(name.equals(dasGenre.get(i).getName())){      // schon vorhanden?
        return dasGenre.get(i); 
      }
      if(name.compareTo(dasGenre.get(i).getName())<1){ // kommt nicht mehr
        Genre g=new Genre(name);
        dasGenre.add(i,g); // an Position i einfügen
        return g;
      }
    }
    Genre g=new Genre(name); // am Ende einfügen
    dasGenre.add(g); // g einfügen
    return g;
  }
  public void einfuegenBuch(String titel,double preis,int seiten,String genre){
    try {
      Genre g = einfuegenGenre(genre);
      try {
       Buch b =new Buch(titel,preis,seiten,g); // neues Buch einfügen
       dasMedium.add(b);
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public void einfuegenDVD(String titel,double preis,int dauer,String genre){
    try {
      Genre g = einfuegenGenre(genre);
      try {
       DVD d =new DVD(titel,preis,dauer,g); // neues Buch einfügen
       dasMedium.add(d);
      }
      catch (IllegalArgumentException e){
        System.out.println(e);
      }
    }
    catch (IllegalArgumentException e){
      System.out.println(e);
    }
  }
  public int getAnzahlBuecher(){
    return dasMedium.size();
  }
  public void ausgebenGenre(){
    System.out.println("Buechersammlung.ausgebenGenre():");
    for(int i=0;i<dasGenre.size();i++){
      System.out.printf("%2d. %s\n",i,dasGenre.get(i).getName());
    }
  }
  public void ausgebenSammlung(){
    System.out.println("Buechersammlung.ausgebenSammlung():");
    for(int i=0;i<dasMedium.size();i++){
      System.out.printf("%3d. ",i+1);
      dasMedium.get(i).ausgebenInfo();
    }
  }
  public void sortierePreis(){
    dasMedium.sort((a,b)->{return a.comparePreis(b);}); // Lambda Ausdruck für sort()
  }
  /*public void sortiereSeiten(){
    dasBuch.sort((a,b)->{return a.compareSeiten(b);});
  }*/
  public void sortiereGenre(){
    dasGenre.sort((a,b)->{return a.compareName(b);});
  }
  public void sortiereGenreRev(){ // String hat Comparable implementiert
    dasGenre.sort((a,b)->{return -1*a.getName().compareTo(b.getName());});
  }
  public void leseCSV(String dateiname){
    int i;
    Path pfad = Paths.get(dateiname); // Dateipfad
    String zeile;
    String[] attribute;
    try { // versuchen wir mal folgenden Code aus zu fuehren
      BufferedReader ein = Files.newBufferedReader(pfad); // oeffne Datenstrom
      while ((zeile = ein.readLine())!= null){ // solange Datensaetze vorhanden, lese Zeile
        zeile=zeile.replace(',','.'); // damit Doubleparsen geht
        attribute = zeile.split(";");
        if(attribute[0].equals("Buch")){
          einfuegenBuch(attribute[1],Double.parseDouble(attribute[2]),Integer.parseInt(attribute[3]),attribute[4]);  
        }
        else if (attribute[0].equals("DVD")){
          einfuegenDVD(attribute[1],Double.parseDouble(attribute[2]),Integer.parseInt(attribute[3]),attribute[4]);  
        }
      }
      ein.close(); // schliesse Datenstrom
    } catch (IOException e) { // falls ein IO-Ausnahmefehler auftritt tue folgendes
      System.out.println("IOException: " + e); // gib den Fehler auf der Konsole aus
    }
  }
  public void schreibeCSV(String dateiname){
    int i;
    Path pfad = Paths.get(dateiname); // Dateipfad
    try {  // versuchen wir mal folgenden Code aus zu fuehren
      Writer aus = Files.newBufferedWriter(pfad); //Datenschreiber
      for(i=0;i<getAnzahlBuecher();i++){
        aus.write(dasMedium.get(i).toCSV()+"\n"); //schreibe
      }
      aus.close(); // schliesse Datenstrom
    } catch (IOException e) {  //falls ein IO-Ausnahmefehler
      System.out.println("IOException: " + e);  //Fehler ausgeben
    }
  }
}
// Medienverwaltung-Ex-Liste v1.0
public class Buch extends Medium {
  private int seiten;     // {>=0}
  public Buch(String titel,double preis,int seiten,Genre genre){
    super(titel,preis,genre);  
    if (seiten<0){
      throw new IllegalArgumentException("Buch: Seitenanzahl negativ"); 
    }
    this.seiten = seiten; 
  }
  public void ausgebenInfo(){
    System.out.printf("Buch:\tTitel: %-30s \tPreis:%7.2f€ \tSeiten:%5d \tGenre: %s\n",getTitel(),getPreis(),seiten,getGenre().getName());
  }
  public int compareSeiten(Buch b){ // Metrik für aufsteigende Sortierung
    if(seiten==b.seiten) return 0;
    if(seiten>b.seiten) return 1;
    return -1;
  }
  public String toCSV(){
    return String.format("Buch;%s;%.2f;%d;%s",getTitel(),getPreis(),seiten,getGenre().getName());
  }
}
// Medienverwaltung-Ex-Liste v1.0
public class DVD extends Medium {
  private int dauer;     // {>=0}
  public DVD(String titel,double preis,int dauer,Genre genre){
    super(titel,preis,genre);  
    if (dauer<0){
      throw new IllegalArgumentException("DVD: Dauer negativ"); 
    }
    this.dauer = dauer; 
  }
  public void ausgebenInfo(){
    System.out.printf("DVD:\tTitel: %-30s \tPreis:%7.2f€ \tDauer:%5d \tGenre: %s\n",getTitel(),getPreis(),dauer,getGenre().getName());
  }
  public int compareDauer(DVD b){ // Metrik für aufsteigende Sortierung
    if(dauer==b.dauer) return 0;
    if(dauer>b.dauer) return 1;
    return -1;
  }
  public String toCSV(){
    return String.format("DVD;%s;%.2f;%d;%s",getTitel(),getPreis(),dauer,getGenre().getName());
  }
}