/*******************************************************************************
 * Copyright (c) 1998, 2011 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.testing.tests.queries;

import java.util.*;

import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.employee.domain.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.sessions.*;

/**
 * Runs cursored stream tests with conforming.
 * @bug 3009570 Conforming Cursors
 * @author Stephen McRitchie
 */
	
public class CursoredStreamConformingTest extends CursoredStreamTest 
{
	protected ConformingTestConfiguration configuration;
	protected boolean useNestedUnitOfWork;

public CursoredStreamConformingTest() {
	super(Employee.class, (new ExpressionBuilder()).get("salary").greaterThan(50000));
	configuration = new ConformingTestConfiguration();
}

public CursoredStreamConformingTest(boolean useNestedUnitOfWork) {
	this();
	if (useNestedUnitOfWork) {
		setName(getName() + ":NestedUnitOfWork");
		this.useNestedUnitOfWork = true;
	}
	
}
protected void setup() 
{	
	getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

	configuration.setup(getSession());
	UnitOfWork unitOfWork = configuration.getUnitOfWork();
	
	ReadAllQuery query = new ReadAllQuery(getReferenceClass(), joinExpression);
	query.conformResultsInUnitOfWork();
	Vector result = (Vector)unitOfWork.executeQuery(query);

	// Since conforming can not preserve order, must simply compare the
	// two results by PK.
	Vector expectedPKs = new Vector(result.size());
	for (Enumeration enumtr = result.elements(); enumtr.hasMoreElements();) {
		Employee emp = (Employee)enumtr.nextElement();
		expectedPKs.add(emp.getId());
	}
	setNormalQueryObjects(expectedPKs);
	
	configuration.reset();
	getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

	configuration.setup(getSession());
	if (useNestedUnitOfWork) {
		getExecutor().setSession(configuration.getUnitOfWork().acquireUnitOfWork());		
	} else {
		getExecutor().setSession(configuration.getUnitOfWork());
	}
}
public void test ( ) {
	
	ReadAllQuery query = new ReadAllQuery();
	CursoredStream stream = null;
	
	try {
		Object databaseObject;
	
		cursoredQueryObjects = new Vector();
	
		query.setReferenceClass(getReferenceClass());
		query.setSelectionCriteria(joinExpression);
		query.conformResultsInUnitOfWork();
		query.useCursoredStream();
		stream = (CursoredStream) getSession().executeQuery(query);
		
		// Test dual cursors and read(int)
		CursoredStream stream2 = (CursoredStream) getSession().executeQuery(query);
		try {
		stream2.read(5);
		} catch (org.eclipse.persistence.exceptions.QueryException ex) {} // ignore at end	
		stream2.close();
		while (!stream.atEnd()) {
			databaseObject = stream.read();		
			getCursoredQueryObjects().addElement(((Employee)databaseObject).getId());
			stream.releasePrevious();	
		}
	} finally {	
		if (stream != null) {
			stream.close();
		}
	}	
}
/**
 * Verify if number of query objects matches number of cursor objects
 */
protected void verify() 
{	
	//System.out.println("Normal objects: " + getNormalQueryObjects());
	//System.out.println("Conforming objects: " + getCursoredQueryObjects());
	if (getNormalQueryObjects().size() != getCursoredQueryObjects().size()) {
		throw new TestErrorException("The number of streamed objects does not match the number of objects stored on the database ");
	}

	if (getNormalQueryObjects().size() == 0) {
		throw new TestWarningException("no object with the specified selection criteria was found ");
	}

	for (Enumeration enumtr = getNormalQueryObjects().elements(); enumtr.hasMoreElements();) {
		Object nextObject = enumtr.nextElement();
		if (!getCursoredQueryObjects().remove(nextObject)) {
			throw new TestErrorException("The following element was not found in the conformed result: " + nextObject);
		}
	}	
}

public void reset() {
	if (useNestedUnitOfWork) {
		getExecutor().getSession().release();
	}
	getExecutor().setSession(configuration.getUnitOfWork().getParent());
	configuration.reset();
}
}
