
package de.ivu.elect.jee.entity;

import java.io.Serializable;
import java.util.stream.Collectors;

import de.ivu.elect.jee.entity.tk.EntityUK;

public abstract class AbstractDAO<E extends Entity, PK, UK extends EntityUK> implements DAO<E, PK, UK>, Serializable {

  private static final long serialVersionUID = 1L;

  protected static final java.util.Map<String, Object> CACHE_PROPERTIES;

  protected abstract javax.persistence.EntityManager getEntityManager();

  public AbstractDAO() {
    super();
  }

  public de.ivu.elect.jee.entity.QueryDsl getQueryDsl() {
    return new de.ivu.elect.jee.entity.QueryDsl(getEntityManager());
  }

  public void clear() {
    getEntityManager().clear();
  }

  public void flush() {
    getEntityManager().flush();
  }

  public void detach(E entity) {
    if (entity != null) {
      getEntityManager().detach(entity);
    }
  }

  protected abstract E findByPrimaryKey(Long id);

  @SuppressWarnings("unchecked")
  protected <T> T checkAndAttach(T t, Class< ? > clazz, String name) {
    if (t == null) {
      throw new java.lang.IllegalArgumentException("Der Parameter " + name + " ist null!");
    }
    if (t instanceof de.ivu.elect.jee.entity.Entity) {
      return (T) getEntityManager().find(clazz, ((de.ivu.elect.jee.entity.Entity) t).getId());
    }
    return t;
  }

  /**
   * Attacht die Entität und aktualisiert ihre Inhalte aus der Datenbank, um veraltete Informationen im First Level Cache zu vergessen.
   * <p/>
   * Cf. ELECT-3187 (Änderungen an Entität werden nicht gespeichert)
   */
  public E refresh(E entity) {
    if (entity == null) {
      return null;
    }
    E attached = attach(entity);// Attach vorher sinnvoll, um Fehler zu vermeiden (z.B. ELECTMUC-1635 )
    getEntityManager().refresh(attached);
    return attached;
  }

  public E attach(@javax.annotation.Nullable E entity) {
    if (entity == null) {
      return null;
    }

    return findByPrimaryKey(entity.getId());
  }

  public java.util.List<E> attachAll(java.util.Collection< ? extends E> entities) {
    return entities.stream().map(this::attach).collect(Collectors.toList());
  }

  static {
    CACHE_PROPERTIES = new java.util.HashMap<>();
    CACHE_PROPERTIES.put("org.hibernate.cacheable", "true");
  }
}
