/*
* 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.
*/
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package it.laitspa.cpf.model;

/**
 *
 * @author Andrea
 */
import java.util.ArrayList;
import java.util.List;

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

public abstract class QueryPaging
{
  private int       firstResult;
  private int       maxResults;

  protected Session session;


  public QueryPaging(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 queryHql = getQueryHql();
    org.hibernate.Query q = session.createQuery(queryHql);
    setQueryLimits(q);
    setQueryArguments(q);
    return q.scroll(ScrollMode.FORWARD_ONLY);
  }

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

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

    // Count the query results.
    //
    String listHql = getListHql();
    q = session.createQuery(listHql);
    setQueryArguments(q);
    List<Object> listId = q.list();
    int count = listId.size();

    result.setCount(count);

    // If no items will be returned by the query,
    // we spare the effort of querying.
    //
    if(count <= 0)
      return result;


    // Retrieve Object by storedId.
    //
    if (firstResult < 0 || firstResult >= listId.size())
      return result;

    int maxRes = firstResult + maxResults;
    
    List<Object> list = new ArrayList<Object>();
    int index = firstResult;
    while (index < listId.size() && index < maxRes)
    {
      Object obj = listId.get(index);
      Object id = null;
      
      if (obj instanceof Object[])
      {
        Object[] ar = (Object[]) obj;
        id = ar[0];
      }
      else
        id = obj;
      
      String queryHql = getQueryHql();
      
      // Set query Properties.
      //
      setSessionProperties(session);
      
      q = session.createQuery(queryHql);
      setQueryId(q, id);
      
      Object res = q.uniqueResult();
      list.add(res);
      index++;
    }
    result.setItems(list);

    // Return the results.
    //
    return result;
  }

  private void setQueryLimits(org.hibernate.Query q)
  {
    q.setFirstResult(firstResult);

    if(maxResults >= 0)
      q.setMaxResults(maxResults);
  }

  protected abstract boolean checkQueryArguments();

  protected abstract String getListHql();

  protected abstract String getQueryHql();

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

  protected void setQueryId(org.hibernate.Query q, Object id)
  {
    q.setParameter("id", id);
  }
  
  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;
  }
  
  protected void setSessionProperties(Session session)
  {
    
  }
}

