/* Autor: Stephan Kleuker
 * Version 1.0 16.10.2009
 * Hinweis: Die hier gezeigten Klassen sind als einführende
 * Beispiele in die JPA-Funktionalität gedacht. Bei größeren
 * Systemen muss über eine Aufteilung der Funktionalität in mehrere
 * Schichten nachgedacht werden.
 */
package jpa20mitbeanvalidation;

import java.util.Collection;
import java.util.Iterator;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import jpa20mitbeanvalidation.entities.Mitarbeiter;
import jpa20mitbeanvalidation.entities.Projekt;
import jpa20mitbeanvalidation.entities.Projektauftrag;
import jpa20mitbeanvalidation.entities.Rolle;

public class Main {

  private EntityManagerFactory eMF =
          Persistence.createEntityManagerFactory("JPA20MitBeanValidationPU");
  private EntityManager em = eMF.createEntityManager();

  /* Einspielen der Daten aus der Vorlesung */

  public void beispieldatenNIO(){
    Mitarbeiter m1 = new Mitarbeiter("X");
    Rolle[] r= { new Rolle("C++", 60),new Rolle("C", 50),new Rolle("Cobol", 70)};
    for(int i=0;i<r.length;i++)
      m1.rolleHinzu(r[i]);
    System.out.println(m1);
    try {
      em.getTransaction().begin();
      em.persist(m1);
      em.getTransaction().commit();
    } catch (ConstraintViolationException e) {
      System.out.println(e.getMessage());
      for(ConstraintViolation c:e.getConstraintViolations())
        System.out.println(c.getMessage());
      em.getTransaction().rollback();
    }
    /*String anfrage = "SELECT m FROM Mitarbeiter m";
    for(Mitarbeiter m:em.createQuery(anfrage, Mitarbeiter.class).getResultList())
    System.out.println(m);*/
  }

  public void beispieldatenIO(){
    Mitarbeiter m1 = new Mitarbeiter("XUrs");
    Rolle[] r= { new Rolle("Java", 60),new Rolle("C", 50)};
    for(int i=0;i<r.length;i++)
      m1.rolleHinzu(r[i]);
    System.out.println(m1);
    try {
      em.getTransaction().begin();
      em.persist(m1);
      em.getTransaction().commit();
    } catch (ConstraintViolationException e) {
      System.out.println(e.getMessage());
      for(ConstraintViolation c:e.getConstraintViolations())
        System.out.println(c.getMessage());
      em.getTransaction().rollback();
    }
    /*String anfrage = "SELECT m FROM Mitarbeiter m";
    for(Mitarbeiter m:em.createQuery(anfrage, Mitarbeiter.class).getResultList())
    System.out.println(m);*/
  }

    public void beispieldaten(){
    Mitarbeiter m1 = new Mitarbeiter("XUrs");
    Mitarbeiter m2 = new Mitarbeiter("Urs");
    Rolle[] r= { new Rolle("Java", 60),new Rolle("C", 50)};
    for(int i=0;i<r.length;i++)
      m1.rolleHinzu(r[i]);
    System.out.println(m1+"\n"+m2);
    try {
      em.getTransaction().begin();
      em.persist(m1);
      em.persist(m2);
      em.getTransaction().commit();
    } catch (ConstraintViolationException e) {
      System.out.println(e.getMessage());
      for(ConstraintViolation c:e.getConstraintViolations())
        System.out.println(c.getMessage());
      em.getTransaction().rollback();
    }
    /*String anfrage = "SELECT m FROM Mitarbeiter m";
    for(Mitarbeiter m:em.createQuery(anfrage, Mitarbeiter.class).getResultList())
    System.out.println(m);*/
  }


  public void beispieldatenAlt() {
    Projekt p1 = new Projekt("Bonitaet");
    Projekt p2 = new Projekt("Bremse");
    Rolle r1 = new Rolle("Java", 60);
    Rolle r2 = new Rolle("C", 50);
    Rolle r3 = new Rolle("Cobol", 70);
    Mitarbeiter m1 = new Mitarbeiter("Ivan");
    Mitarbeiter m2 = new Mitarbeiter("Fatma");
    Mitarbeiter m3 = new Mitarbeiter("Urs");
    Mitarbeiter m4 = new Mitarbeiter("Heinz");
    Projektauftrag pa[] = {new Projektauftrag("Historie"),
      new Projektauftrag("Konten"),
      new Projektauftrag("Raten"),
      new Projektauftrag("Sensoren"),
      new Projektauftrag("Fusion"),
      new Projektauftrag("Display")};
    for (int i = 0; i < 3; i++) {
      p1.projektauftragHinzu(pa[i]);
      p2.projektauftragHinzu(pa[i + 3]);
    }
    m1.rolleHinzu(r1);
    r1.mitarbeiterHinzu(m1);
    m1.rolleHinzu(r2);
    r2.mitarbeiterHinzu(m1);

    m2.rolleHinzu(r1);
    r1.mitarbeiterHinzu(m2);
    m2.rolleHinzu(r3);
    r3.mitarbeiterHinzu(m2);

    m3.rolleHinzu(r1);
    r1.mitarbeiterHinzu(m3);
    m4.rolleHinzu(r2);
    r2.mitarbeiterHinzu(m4);

    pa[0].setRolle(r1);
    pa[1].setRolle(r3);
    pa[2].setRolle(r1);
    pa[3].setRolle(r2);
    pa[4].setRolle(r2);
    pa[5].setRolle(r1);

    pa[0].setBearbeiter(m3);
    m3.auftragHinzu(pa[0]);
    pa[1].setBearbeiter(m2);
    m2.auftragHinzu(pa[1]);
    pa[2].setBearbeiter(m1);
    m1.auftragHinzu(pa[2]);
    pa[3].setBearbeiter(m1);
    m1.auftragHinzu(pa[3]);
    pa[4].setBearbeiter(m1);
    m1.auftragHinzu(pa[4]);
    pa[5].setBearbeiter(m2);
    m2.auftragHinzu(pa[5]);

    Object o[] = {m1, m2, m3, m4, p1, p2};

    em.getTransaction().begin();
    for (int i = 0; i < o.length; i++) {
      em.persist(o[i]);
    }
    em.getTransaction().commit();

  }

  /* Hilfsabfrage ob Tabelle tabelle existiert */
  public boolean existenzPruefen(String tabelle) {
    try {
      em.createQuery("SELECT o FROM " + tabelle + " o");
      return true;
    } catch (IllegalArgumentException e) {
      return false;
    }
  }

  /* Interaktives Anfragewerkzeug, Anfragen über mehrere Zeilen
   * möglich. Am Ende der Abfrage muss ein Semikolon stehen. */
  public void anfragen() {
    String anfrage = "";
    while (!anfrage.toUpperCase().equals("ENDE ")) {
      anfrage = "";
      System.out.println("Anfrage eingeben (Programmende mit ENDE, "
              + "am Anfrageende ein ;)");
      while (!anfrage.toUpperCase().equals("ENDE ") && !anfrage.endsWith("; ")) {
        anfrage += Eingabe.leseString() + " ";
      }
      if (!anfrage.toUpperCase().equals("ENDE ")) {
        anfrage = anfrage.substring(0, anfrage.length() - 2);
        try {
          Query query = em.createQuery(anfrage);
          Collection erg = query.getResultList();
          for (Iterator it = erg.iterator(); it.hasNext();) {
            System.out.println(it.next());
          }
        } catch (Exception e) {
          System.out.println("Anfrage gescheitert: " + e.getMessage());
        }
        anfragen2(anfrage); // nur sinnvoll, wenn Array als Ergebnis
      }
    }
  }

  /* Ausführung der Anfrage ql, für die eine "normale" Liste von
   * Objekten als Ergebnis erwartet wird. */
  public void anfragen(String ql) {
    System.out.println(ql);
    try {
      Query query = em.createQuery(ql);
      Collection erg = query.getResultList();
      for (Iterator it = erg.iterator(); it.hasNext();) {
        System.out.println(it.next());
      }
    } catch (Exception e) {
      System.out.println("Anfrage gescheitert: " + e.getMessage());
    } finally {
      System.out.println("-------------------");
    }
  }

  /* Detailliertere Analyse des Ergebnisses der Anfrage ql, falls
   * Object-Arrays in der Ergebnisliste stehen, werden Elemente der
   * Arrays einzeln ausgegeben. */
  public void anfragen2(String ql) {
    System.out.println(ql);
    try {
      Query query = em.createQuery(ql);
      Collection erg = query.getResultList();
      for (Iterator it = erg.iterator(); it.hasNext();) {
        Object o = it.next();
        System.out.println(o + " :: " + o.getClass().getName());
        if (o.getClass().getName().equals("[Ljava.lang.Object;")) {
          Object oa[] = (Object[]) o;
          for (int i = 0; i < oa.length; i++) {
            System.out.println("  " + oa[i]);
          }
        }
      }
    } catch (Exception e) {
      System.out.println("Anfrage gescheitert: " + e.getMessage());
    }
  }

  public void anzeigen() {
    String entitaeten[] = {"Mitarbeiter", "Projektauftrag", "Projekt", "Rolle"};
    for (int i = 0; i
            < entitaeten.length; i++) {
      String anfrage = "SELECT o FROM " + entitaeten[i] + " o";
      Query query = em.createQuery(anfrage);
      Collection erg = query.getResultList();
      System.out.println(entitaeten[i]);
      for (Iterator it = erg.iterator(); it.hasNext();) {
        System.out.println(it.next());
      }

    }
  }

  public void projektVon(String name) {
    anfragen("SELECT p.name FROM Projekt p JOIN p.auftraege pa "
            + "WHERE pa.bearbeiter.name='" + name + "'");
  }

  /* nur zu Demozwecken als Variante */
  private static final String PROJEKT_VON =
          "SELECT p.name FROM Projekt p JOIN p.auftraege pa "
          + "WHERE pa.bearbeiter.name= :mname";

  public void projektVon2(String name) {
    Query query = em.createQuery(PROJEKT_VON).setParameter("mname", name);
    Collection erg = query.getResultList();
    for (Iterator it = erg.iterator(); it.hasNext();) {
      System.out.println(it.next());
    }
  }

  /* Achtung, das Durchreichen eines EntityManager-Objekts an die
   * Entity-Schicht sollte vermieden werden.
   * Beispiel so gewählt, um es minimal zu halten */
  public void zeigeMitarbeiter(int minr) {
    System.out.println(Mitarbeiter.zuMinr(minr, em));
    Mitarbeiter m = em.createNamedQuery("Mitarbeiter.primaryKey", Mitarbeiter.class).
            setParameter("minr", minr).getSingleResult();
  }

  public void zeigeMAMitFaehigkeiten(String faehigkeit) {
    System.out.println(" :: " + faehigkeit);
    for (Mitarbeiter m : em.createNamedQuery("Mitarbeiter.mitFaehigkeit", Mitarbeiter.class).
            setParameter("name", faehigkeit).getResultList()) {
      System.out.println(m);
    }
  }

  public void schliessen() {
    if (em != null && em.isOpen()) {
      em.close();
    }
    if (eMF != null && eMF.isOpen()) {
      eMF.close();
    }
  }

  public static void main(String[] args) {
    Main jpa = new Main();

    jpa.beispieldaten();

    jpa.anzeigen();

    jpa.schliessen();
  }
}
