/***************************************************************/
/* Prof. Dr. Carsten Vogt                                      */
/* FH Koeln, Fak. 07 / Nachrichtentechnik                      */
/* http://www.nt.fh-koeln.de/vogt                              */
/*                                                             */
/* Das Programm zeigt die Implementation einer Queue (= Warte- */
/* schlange mit FIFO-Zugriffsreihenfolge). Die Queue wird mit  */
/* Hilfe eines Arrays des Typs Object[] realisiert, so dass in */
/* ihr Objekte beliebiger Klassen (auch unterschiedlicher Klas-*/
/* sen durchmischt) abgelegt werden können.                    */
/* Bei dieser Implementation wird keine generische Klasse be-  */
/* nutzt.                                                      */ 
/***************************************************************/

import java.io.*;

// Definition der Queue-Klasse

class Queue {
 
  private Object[] inhalt = null;
                             // Array zur Speicherung der Einträge der Queue.
                             // Der Array ist als "Ringpuffer" organisiert: Zwei Indizes (s.u.) bezeichnen
                             // die Arraypositionen, an denen der nächste Lese- bzw. Schreibzugriff stattfindet.
                             // Ein Index wird nach einer Lese- bzw. Schreiboperation um 1 erhöht und dabei
                             // auf 0 zurückgesetzt, wenn das Arrayende erreicht ist.

  private int laenge,        // Länge des Arrays (= maximale Anzahl von Einträgen + 1). Eine Position bleibt
                             // stets leer, um die Fälle "Queue voll" und "Queue leer" unterscheiden zu
                             // können (siehe unten).
 
              leseIndex,     // An der Arrayposition 'leseIndex' findet der nächste Lesezugriff statt.

              schreibIndex;  // An der Arrayposition '(schreibIndex+1)%laenge'
                             // findet der nächste Lesezugriff statt.

  Queue(int maxAnzahlEintraege){
    laenge = maxAnzahlEintraege+1;
    inhalt = new Object[laenge];
    leseIndex = schreibIndex = 0;
   }

  public boolean leer() {
   // Die Queue ist leer, wenn Lese- und Schreibindex auf dieselbe Position zeigen.
   return schreibIndex==leseIndex;
  }

  public boolean voll() {
   // Die Queue ist voll, wenn nach einer Schreiboperation der Schreibindex auf dieselbe Position
   // wie der Leseindex verweisen würde.
   return (schreibIndex+1)%laenge==leseIndex;
  }

  public boolean add(Object o) { // Hinzufügen eines neuen Eintrags an das Queue-Ende
   if (voll())
    return false;
   inhalt[schreibIndex] = o;
   schreibIndex = (schreibIndex+1)%laenge;
   return true;
  }

  public Object remove() { // Entfernen der Eintrags von der Queue-Spitze
   if (leer())
    return null;
   Object erg = inhalt[leseIndex];
   leseIndex = (leseIndex+1)%laenge;
   return erg;
  }

  public String toString() { // Hilfsmethode zur Ausgabe des Queueinhalts
   String erg = new String();
   int i = leseIndex;
   while(i!=schreibIndex) {
    erg += inhalt[i] + " ";
    i = (i+1)%laenge;
   }
   return erg;
  }

}

// Hauptprogramm

public class QueueNichtGenerisch {

 public static void main(String args[]) throws IOException {

  BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

  int choice, maxEintraege;

  Queue queue;

  // Erzeugung der Queue

  System.out.println();
  System.out.print("Gewuenschte maximale Anzahl von Eintraegen der Queue: ");
  maxEintraege = Integer.parseInt(in.readLine());

  queue = new Queue(maxEintraege);

  if (queue!=null) {
     System.out.println();
     System.out.println("Queue erfolgreich erzeugt");
    }
   else {
     System.out.println();
     System.out.println("Erzeugung fehlgeschlagen");
     System.exit(-1);
    }

  // Schleife zur Durchfuehrung von Operationen auf der Queue

  do {

   System.out.println();
   System.out.println("Bitte waehlen:");
   System.out.println(" 1: Eintrag einfuegen");
   System.out.println(" 2: Eintrag ausfuegen");
   System.out.println(" 3: Queue voll?");
   System.out.println(" 4: Queue leer?");
   System.out.println(" 5: Queue-Inhalt ausgeben");
   System.out.println(" 0: Ende");
   do {
    choice = Integer.parseInt(in.readLine());
   } while (choice<0||choice>5);

   System.out.println();

   switch(choice) {

    case 0: break;

    case 1: System.out.println();
            System.out.print("Einzufuegender Eintrag: ");
            String s_in = in.readLine();
            if (queue.add(s_in))
              System.out.println("--> Einfuegen erfolgreich");
             else
              System.out.println("--> Einfuegen fehlgeschlagen");
            break;

    case 2: String s_out = (String) queue.remove();
            if (s_out!=null)
              System.out.println("--> Ausgefuegt: "+s_out);
             else
              System.out.println("--> Ausfuegen fehlgeschlagen");
            break;

    case 3: if (queue.voll())
              System.out.println("--> Queue ist voll");
             else
              System.out.println("--> Queue ist nicht voll");
            break;

    case 4: if (queue.leer())
              System.out.println("--> Queue ist leer");
             else
              System.out.println("--> Queue ist nicht leer");
            break;

    case 5: System.out.println(queue.toString());
            break;

   }

  } while (choice!=0);

 }

}

