// Path: rsterminology-core/src/main/java/com/eldrix/terminology/cayenne/CayenneUtility.java
// public class CayenneUtility {
// 
// 	/**
// 	 * A very simple helper method to iterate through a select query showing progress.
// 	 * Most useful in a command line utility.
// 	 */
// 	public static <T> void timedBatchIterator(ObjectContext context, SelectQuery<T> query, int batchSize, long count, Consumer<List<T>> forEach) {
// 		long i = 1;
// 		long batches = (count / batchSize) + (count % batchSize > 0 ? 1 : 0);
// 		long estimated = 0;
// 		System.out.println("Processing " + count + ((batches == 0) ? "" : (" in " + batches + " batches...")));
// 		long start = System.currentTimeMillis();
// 		try (ResultBatchIterator<T> iterator = query.batchIterator(context, batchSize)) {
// 			for(List<T> batch : iterator) {
// 				System.out.print("\rProcessing batch " + i + "/" + batches + (estimated == 0 ? "" : " Remaining: ~" + estimated / 60000 + " min   "));
// 				forEach.accept(batch);
// 				i++;
// 				long elapsed = System.currentTimeMillis() - start;
// 				estimated = (batches - i) * elapsed / i;
// 			}
// 		}
// 		long duration = System.currentTimeMillis() - start;
// 		System.out.println("\nFinished processing : " + count + " Total time:" + duration / 60000 + " minutes");
// 	}
// 
// }


import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.map.SQLResult;
import org.apache.cayenne.query.EJBQLQuery;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import com.eldrix.terminology.cayenne.CayenneUtility;
		query.setFetchingDataRows(true);
		return query;
	}
	
	/**
	 * Return the recursive parents for the given concept.
	 * @param context
	 * @param conceptId
	 * @return
	 */
	public static List<Long> fetchRecursiveParentsForConcept(ObjectContext context, long conceptId) {
		SQLTemplate query = _sqlTemplateForRecursiveParentsForConcept(conceptId);
		SQLResult resultDescriptor = new SQLResult();
		resultDescriptor.addColumnResult("concept_id");
		query.setResult(resultDescriptor);
		@SuppressWarnings("unchecked") List<Long> result =  context.performQuery(query);
		return result;
	}
	
	/**
	 * Build the cached parent concept cache.
	 * This will naturally take a considerable amount of time to process and it is suggested that this be run
	 * within a background task.
	 */
	public static void buildParentCache(ObjectContext context) {
		EJBQLQuery countQuery = new EJBQLQuery("select COUNT(c) FROM Concept c");
		@SuppressWarnings("unchecked")
		long count = ((List<Long>) context.performQuery(countQuery)).get(0);
		SelectQuery<Concept> query = SelectQuery.query(Concept.class);
		System.out.println("Building parent cache...");
// Path: rsterminology-core/src/main/java/com/eldrix/terminology/cayenne/CayenneUtility.java
// public class CayenneUtility {
// 
// 	/**
// 	 * A very simple helper method to iterate through a select query showing progress.
// 	 * Most useful in a command line utility.
// 	 */
// 	public static <T> void timedBatchIterator(ObjectContext context, SelectQuery<T> query, int batchSize, long count, Consumer<List<T>> forEach) {
// 		long i = 1;
// 		long batches = (count / batchSize) + (count % batchSize > 0 ? 1 : 0);
// 		long estimated = 0;
// 		System.out.println("Processing " + count + ((batches == 0) ? "" : (" in " + batches + " batches...")));
// 		long start = System.currentTimeMillis();
// 		try (ResultBatchIterator<T> iterator = query.batchIterator(context, batchSize)) {
// 			for(List<T> batch : iterator) {
// 				System.out.print("\rProcessing batch " + i + "/" + batches + (estimated == 0 ? "" : " Remaining: ~" + estimated / 60000 + " min   "));
// 				forEach.accept(batch);
// 				i++;
// 				long elapsed = System.currentTimeMillis() - start;
// 				estimated = (batches - i) * elapsed / i;
// 			}
// 		}
// 		long duration = System.currentTimeMillis() - start;
// 		System.out.println("\nFinished processing : " + count + " Total time:" + duration / 60000 + " minutes");
// 	}
// 
// }


// Path: rsterminology-core/src/main/java/com/eldrix/terminology/snomedct/ParentCache.java
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.map.SQLResult;
import org.apache.cayenne.query.EJBQLQuery;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import com.eldrix.terminology.cayenne.CayenneUtility;

		query.setFetchingDataRows(true);
		return query;
	}
	
	/**
	 * Return the recursive parents for the given concept.
	 * @param context
	 * @param conceptId
	 * @return
	 */
	public static List<Long> fetchRecursiveParentsForConcept(ObjectContext context, long conceptId) {
		SQLTemplate query = _sqlTemplateForRecursiveParentsForConcept(conceptId);
		SQLResult resultDescriptor = new SQLResult();
		resultDescriptor.addColumnResult("concept_id");
		query.setResult(resultDescriptor);
		@SuppressWarnings("unchecked") List<Long> result =  context.performQuery(query);
		return result;
	}
	
	/**
	 * Build the cached parent concept cache.
	 * This will naturally take a considerable amount of time to process and it is suggested that this be run
	 * within a background task.
	 */
	public static void buildParentCache(ObjectContext context) {
		EJBQLQuery countQuery = new EJBQLQuery("select COUNT(c) FROM Concept c");
		@SuppressWarnings("unchecked")
		long count = ((List<Long>) context.performQuery(countQuery)).get(0);
		SelectQuery<Concept> query = SelectQuery.query(Concept.class);
		System.out.println("Building parent cache...");
		CayenneUtility.timedBatchIterator(context, query, BATCH_SIZE, count, (concepts) -> {