/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")– non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* È possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
/**
 * 
 */
package it.laitspa.cpf.model;


import java.math.BigDecimal;
import java.math.BigInteger;

import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;


/**
 * @author Andrea
 * 
 */
public abstract class EntityQuery
{
  private int       firstResult;
  private int       maxResults;

  protected Session session;
  
  public EntityQuery(Session session)
  {
    firstResult = 0;
    maxResults = 10;
    this.session = session;
  }

  public ScrollableResults scroll()
  {
    // Check query arguments.
    //
    if(!checkQueryArguments())
      throw new IllegalArgumentException();

    // Initialize hibernate session and query objects.
    //
    // Execute the query.
    //
    String querySql = getQuerySql();
    org.hibernate.SQLQuery q = session.createSQLQuery(querySql);
    setQueryLimits(q);
    setQueryArguments(q);
    setQueryEntities(q);
    return q.scroll(ScrollMode.FORWARD_ONLY);
  }

  public QueryResult query()
  { 
    // Check query arguments.
    //
    if(!checkQueryArguments())
      throw new IllegalArgumentException();

    // Initialize hibernate session and query objects.
    //
    QueryResult result = new QueryResult();
    org.hibernate.SQLQuery q;

    // Count the query results.
    //
    String countSql = getCountSql();
    q = session.createSQLQuery(countSql);
    setQueryArguments(q);    
    Object o = q.uniqueResult();

    int count = 0;
    if(o instanceof Integer)
      count = ((Integer)o).intValue();
    else if(o instanceof Long)
      count = ((Long)o).intValue();
    else if(o instanceof BigInteger)
      count = ((BigInteger)o).intValue();
    else if(o instanceof BigDecimal)
      count = ((BigDecimal)o).intValue();
    else
      throw new IllegalArgumentException("Unexpected type found when counting query.");
    
    result.setCount(count);
    
    // If no items will be returned by the query,
    // we spare the effort of querying.
    //
    if(count <= 0)
      return result;
    
    
    // Execute the query.
    //
    String querySql = getQuerySql();
    q = session.createSQLQuery(querySql);
    setQueryLimits(q);
    setQueryArguments(q);
    setQueryEntities(q);
    result.setItems(q.list());
    
    // Return the results.
    //
    return result;
  }

  private void setQueryLimits(org.hibernate.Query q)
  {
    q.setFirstResult(firstResult);
    q.setMaxResults(maxResults);
  }
  
  protected abstract void setQueryEntities(org.hibernate.SQLQuery q);

  protected abstract boolean checkQueryArguments();

  protected abstract String getCountSql();

  protected abstract String getQuerySql();

  protected abstract void setQueryArguments(org.hibernate.SQLQuery q);

  public int getFirstResult()
  {
    return firstResult;
  }

  public void setFirstResult(int firstResult)
  {
    this.firstResult = firstResult;
  }

  public int getMaxResults()
  {
    return maxResults;
  }

  public void setMaxResults(int maxResults)
  {
    this.maxResults = maxResults;
  }
}
