/**
 * 
 */
package org.openforis.collect.io.metadata;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.openforis.collect.io.metadata.parsing.ParsingError;
import org.openforis.commons.collection.CollectionUtils;
import org.openforis.concurrency.Task;

/**
 * @author S. Ricci
 *
 */
public abstract class ReferenceDataImportTask<E extends ParsingError> extends Task {

	private Map<Long, List<E>> rowToErrors;
	private List<Long> processedRows;
	
	public ReferenceDataImportTask() {
		super();
		this.processedRows = new ArrayList<Long>();
		this.rowToErrors = new LinkedHashMap<Long, List<E>>();
	}
	
	protected synchronized void addParsingError(long row, E error) {
		List<E> list = rowToErrors.get(row);
		if ( list == null ) {
			list = new ArrayList<E>();
			rowToErrors.put(row, list);
		}
		if ( ! list.contains(error) ) {
			list.add(error);
		}
	}
	
	protected void addParsingError(E error) {
		long row = error.getRow();
		if ( row > 0 ) {
			addParsingError(row, error);
		} else {
			throw new IllegalArgumentException("Error row must be greater than zero");
		}
	}
	
	protected synchronized void addProcessedRow(long rowNumber) {
		incrementProcessedItems();
		processedRows.add(rowNumber);
	}
	
	public synchronized List<E> getErrors() {
		Collection<List<E>> errorsPerRows = rowToErrors.values();
		List<E> result = new ArrayList<E>();
		for (List<E> errros : errorsPerRows) {
			result.addAll(errros);
		}
		return result;
	}
	
	public synchronized boolean hasErrors() {
		return rowToErrors != null && ! rowToErrors.isEmpty();
	}

	public synchronized List<Long> getProcessedRows() {
		return processedRows;
	}
	
	public synchronized boolean isRowProcessed(long rowNumber) {
		return processedRows.contains(rowNumber);
	}
	
	public synchronized boolean isRowInError(long rowNumber) {
		return rowToErrors.containsKey(rowNumber);
	}
	
	public synchronized Collection<Long> getRowsInError() {
		return rowToErrors.keySet();
	}
	
	public synchronized List<Long> getSkippedRows() {
		List<Long> result = new ArrayList<Long>();
		for (long i = 1; i <= getTotalItems(); i++) {
			if ( ! processedRows.contains(i) ) {
				result.add(i);
			}
		}
		return CollectionUtils.unmodifiableList(result);
	}

}

@@ -132,24 +132,38 @@
 .util.Li
-nkedHash
+st;%0D%0Aimport java.util.
 Map;%0D%0Aim
@@ -169,35 +169,34 @@
 mport java.util.
-Lis
+Se
 t;%0D%0Aimport java.
@@ -200,19 +200,50 @@
 va.util.
-Map
+TreeMap;%0D%0Aimport java.util.TreeSet
 ;%0D%0A%0D%0Aimp
@@ -577,19 +577,18 @@
 private 
-Lis
+Se
 t%3CLong%3E 
@@ -678,32 +678,30 @@
 dRows = new 
-ArrayLis
+TreeSe
 t%3CLong%3E();%0D%0A
@@ -729,18 +729,12 @@
 new 
-LinkedHash
+Tree
 Map%3C
@@ -1798,32 +1798,52 @@
 s() %7B%0D%0A%09%09return 
+new ArrayList%3CLong%3E(
 processedRows;%0D%0A
@@ -1835,24 +1835,25 @@
 rocessedRows
+)
 ;%0D%0A%09%7D%0D%0A%09%0D%0A%09p

Improve reference data import performance