@Override
  public List<Event> getChildAdoptionRecords(Person person) {
    // get the birth records of the children of this parent
    List<Adoption> adoptionRecords = new ArrayList<Adoption>();
    em.getTransaction().begin();
    TypedQuery<Adoption> q =
        em.createQuery(
            "select b from Adoption b, IN(b.parents) p WHERE p.id = :idParam", Adoption.class);
    q.setParameter("idParam", person.getId());

    adoptionRecords.addAll(q.getResultList());

    List<Event> adoptions = new ArrayList<Event>();
    for (Adoption b : adoptionRecords) {
      if (b != null) {
        AdoptedChildRecord cr = new AdoptedChildRecord();
        cr.setEventDate(b.getEventDate());
        cr.setPerson(person);
        cr.setChild(b.getPerson());
        cr.setTown(b.getTown());
        cr.setState_province(b.getState_province());
        cr.setCountry(b.getCountry());
        adoptions.add(cr);
      }
    }
    em.getTransaction().commit();
    return adoptions;
  }
  @Override
  public List<Event> getChildrenBirths(Person person) {
    // get the birth records of the children of this parent
    List<Birth> birthRecords = new ArrayList<Birth>();
    em.getTransaction().begin();
    Query q = em.createQuery("select b from Birth b, IN(b.parents) p WHERE p.id = :idParam");
    q.setParameter("idParam", person.getId());

    birthRecords.addAll((Collection<? extends Birth>) q.getResultList());

    List<Event> childrenBirths = new ArrayList<Event>();
    for (Birth b : birthRecords) {
      if (b != null) {
        ChildRecord cr = new ChildRecord();
        cr.setEventDate(b.getEventDate());
        cr.setPerson(person);
        cr.setChild(b.getPerson());
        cr.setTown(b.getTown());
        cr.setState_province(b.getState_province());
        cr.setCountry(b.getCountry());
        childrenBirths.add(cr);
      }
    }
    em.getTransaction().commit();
    return childrenBirths;
  }
 @Override
 public Adoption findAdoptionRecord(Person person) {
   // Could be null
   em.getTransaction().begin();
   Query q = em.createQuery("select a from Adoption a WHERE a.person.id = :idParam");
   q.setParameter("idParam", person.getId());
   List<Adoption> results = (List<Adoption>) q.getResultList();
   em.getTransaction().commit();
   return (results != null && results.size() > 0) ? results.get(0) : null;
 }
 @SuppressWarnings("unchecked")
 @Override
 public Person getPerson(Long id) {
   em.getTransaction().begin();
   Query q = em.createQuery("select p from Person p where p.id = :idParam");
   q.setParameter("idParam", id);
   List<Person> people = (List<Person>) q.getResultList();
   em.getTransaction().commit();
   return (people != null) ? people.get(0) : null;
 }
  @Override
  public List<Event> findAllEvents(Person person) {
    List<Event> allEvents = new ArrayList<Event>();
    // Polymorphic queries don't work for
    // @MappedSuperclass entities ! :-(
    Event e = findBirthRecord(person);
    if (e != null) {
      allEvents.add(e);
    }
    e = findDeathRecord(person);
    if (e != null) {
      allEvents.add(e);
    }
    e = findAdoptionRecord(person);
    if (e != null) {
      allEvents.add(e);
    }
    allEvents.addAll(findMarriages(person));
    allEvents.addAll(findDivorces(person));
    allEvents.addAll(getChildrenBirths(person));
    allEvents.addAll(getChildAdoptionRecords(person));

    System.out.println("findAllEvents: size of allEvents = " + allEvents.size());
    return allEvents;
  }
  @Override
  public List<Divorce> findDivorces(Person person) {
    List<Divorce> divorces = new ArrayList<Divorce>();
    em.getTransaction().begin();
    Query q = em.createQuery("select d from Divorce d WHERE d.person.id = :personId");
    q.setParameter("personId", person.getId());

    divorces.addAll((Collection<? extends Divorce>) q.getResultList());
    em.getTransaction().commit();
    return divorces;
  }
  @Override
  public List<Marriage> findMarriages(Person person) {
    List<Marriage> marriages = new ArrayList<Marriage>();
    em.getTransaction().begin();
    Query q = em.createQuery("select m from Marriage m WHERE m.person.id = :personId");
    q.setParameter("personId", person.getId());

    marriages.addAll((Collection<? extends Marriage>) q.getResultList());
    em.getTransaction().commit();
    return marriages;
  }
  @Override
  public Death findDeathRecord(Person person) {
    // Could be null
    List<Death> myresults = new ArrayList<Death>();

    em.getTransaction().begin();
    TypedQuery<Death> q =
        em.createQuery("select b from Death b WHERE b.person.id = :idParam", Death.class);
    q.setParameter("idParam", person.getId());

    myresults.addAll(q.getResultList());
    em.getTransaction().commit();
    return myresults.size() >= 1 ? myresults.get(0) : null;
  }
  @Override
  public List<Person> getSpouses(Person person) {
    List<Person> people = new ArrayList<Person>();
    em.getTransaction().begin();
    Query q =
        em.createQuery(
            "select m.spouse from Marriage m "
                + "WHERE m.person.id = :personId order by m.eventdate desc");
    q.setParameter("personId", person.getId());

    people.addAll((Collection<? extends Person>) q.getResultList());
    em.getTransaction().commit();
    return people;
  }
  @Override
  public Set<Person> getSiblingsAll(Person thisPerson) {
    // return full and half siblings of thisPerson
    // exclude thisPerson from the set

    Set<Person> siblings = new HashSet<Person>();
    List<Person> parents = new ArrayList<Person>();

    em.getTransaction().begin();
    Query q =
        em.createQuery(
            "select b.parents from Birth b, IN(b.person) p WHERE p.id = :personId"
                + " or p.id = :parent2Id");
    q.setParameter("personId", thisPerson.getId());

    parents.addAll((Collection<? extends Person>) q.getResultList());

    if (!parents.isEmpty()) {
      if (parents.size() == 2) {
        siblings = getChildrenAll(parents.get(0), parents.get(1));
      } else if (parents.size() == 1) {
        siblings = getChildren(parents.get(0));
      }
    }
    em.getTransaction().commit();
    siblings.remove(thisPerson);
    return siblings;
  }
  @Override
  public void addAdoptedParent(Person child, Person parent) {
    em.getTransaction().begin();
    TypedQuery<Adoption> q =
        em.createQuery("select b from Adoption b where b.person.id = :idParam", Adoption.class);
    q.setParameter("idParam", child.getId());

    List<Adoption> results = (List<Adoption>) q.getResultList();
    Adoption a = (results != null && results.size() > 0) ? results.get(0) : null;
    if (a != null) {
      a.addParent(parent);
      em.merge(a);
    }
    em.getTransaction().commit();
  }
  @Override
  public void addParent(Person child, Person parent) {
    em.getTransaction().begin();
    TypedQuery<Birth> q =
        em.createQuery("select b from Birth b where b.person.id = :idParam", Birth.class);
    q.setParameter("idParam", child.getId());

    List<Birth> results = (List<Birth>) q.getResultList();
    Birth b = (results != null && results.size() > 0) ? results.get(0) : null;
    if (b != null) {
      b.addParent(parent);
      em.merge(b);
    }
    em.getTransaction().commit();
  }