package org.minimalj.repository.list;

import java.io.Serializable;
import java.util.AbstractList;
import java.util.List;

import org.minimalj.backend.Backend;
import org.minimalj.model.Keys;
import org.minimalj.model.properties.PropertyInterface;
import org.minimalj.repository.Repository;
import org.minimalj.repository.query.Order;
import org.minimalj.repository.query.Query;
import org.minimalj.repository.query.Query.QueryLimitable;
import org.minimalj.repository.query.Query.QueryOrderable;
import org.minimalj.util.ClassHolder;
import org.minimalj.util.Sortable;

/**
 * A repository may (but is not required to) return a QueryResultList when the
 * find method is called. Only the size of the list is calculated when a
 * QueryResultList is calculated. Every element read with a get(index) is loaded
 * from the backend.
 * <p>
 * 
 * If you know you will use many elements of the List use the subList method to
 * load a complete range of elements in a unmodifiable List. This is how such
 * lists are used by the Frontend
 * <p>
 *
 * A QueryResultList is unmodifiable. Every call of a add or remove method will
 * result in a UnsupportedOperationException.
 * <p>
 * 
 * If the database has changed before you call a get or subList method you may
 * get <code>null</code> as element or a unexpected reduced sub list. You don't
 * get an exception in that cases.
 * <p>
 * 
 * QueryResultList is Sortable. The order of the elements can be changed at any
 * time. The size of the List is not recalculated and the sub List created
 * before a sort are not updated. Of course this is mainly used by a Frontend.
 * Business methods should execute a new find on the Repository / Backend.
 * <p>
 *
 * @param <T>
 *            Class of the Elements
 */
public class QueryResultList<T> extends AbstractList<T> implements Sortable, Serializable {
	private static final long serialVersionUID = 1L;

	private transient Repository repository;

	private final ClassHolder<T> clazz;

	private QueryLimitable query;
	private final int size;
	
	public QueryResultList(Repository repository, Class<T> clazz, QueryLimitable query) {
		this.repository = repository;
		this.clazz = new ClassHolder<>(clazz);
		this.query = query;
		
		this.size = (int) repository.count(clazz, query);
	}
	
	private Repository getRepository() {
		return repository != null ? repository : Backend.getInstance().getRepository();
	}
	
	@Override
	public T get(int index) {
		Query limtedCriteria = query.limit(index, 1);
		List<T> result = getRepository().find(clazz.getClazz(), limtedCriteria);
		return result.isEmpty() ? null : result.get(0);
	}
	
	@Override
	public List<T> subList(int fromIndex, int toIndex) {
		Query limtedCriteria = query.limit(fromIndex, toIndex - fromIndex);
		List<T> result = getRepository().find(clazz.getClazz(), limtedCriteria);
		return result;
	}
	
	@Override
	public int size() {
		return size;
	}

	@Override
	public void sort(Object[] sortKeys, boolean[] sortDirections) {
		while (query instanceof Order) {
			query = ((Order) query).getQuery();
		}
		for (int i = 0; i<sortKeys.length; i++) {
			PropertyInterface property = Keys.getProperty(sortKeys[i]);
			query = ((QueryOrderable) query).order(property, sortDirections[i]);
		}
	}
	
	@Override
	public boolean canSortBy(Object sortKey) {
		return true;
	}

}

@@ -160,16 +160,81 @@
 ckend;%0D%0A
+import org.minimalj.backend.repository.ReadCriteriaTransaction;%0D%0A
 import o
@@ -2408,137 +2408,8 @@
 %0A%09%0D%0A
-%09private Repository getRepository() %7B%0D%0A%09%09return repository != null ? repository : Backend.getInstance().getRepository();%0D%0A%09%7D%0D%0A%09%0D%0A
 %09@Ov
@@ -2408,32 +2408,32 @@
 %0A%09%0D%0A%09@Override%0D%0A
+
 %09public T get(in
@@ -2516,47 +2516,13 @@
 t = 
-getRepository().find(clazz.getClazz(), 
+find(
 limt
@@ -2582,35 +2582,34 @@
 lt.get(0);%0D%0A%09%7D%0D%0A
-%09
 %0D%0A
+
 %09@Override%0D%0A%09pub
@@ -2736,29 +2736,122 @@
 %0D%0A%09%09
-List%3CT%3E result = getR
+return find(limtedCriteria);%0D%0A%09%7D%0D%0A%0D%0A%09private List%3CT%3E find(Query limtedCriteria) %7B%0D%0A%09%09return repository != null ? r
 epos
@@ -2855,18 +2855,16 @@
 pository
-()
 .find(cl
@@ -2894,34 +2894,105 @@
 riteria)
-;
 %0D%0A%09%09
-return result
+%09%09: Backend.execute(new ReadCriteriaTransaction%3CT%3E(clazz.getClazz(), limtedCriteria))
 ;%0D%0A%09%7D%0D%0A%09

fix for SocketBackend