/*******************************************************************************
 * Copyright (c) 2005, 2009 SAP. 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:
 *     SAP - initial API and implementation
 ******************************************************************************/

package org.eclipse.persistence.testing.tests.wdf.jpa1.query;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.eclipse.persistence.platform.database.SQLServerPlatform;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.Skip;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Cubicle;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestNativeQuery extends JPA1Base {
    private final Set<Department> ALL_DEPARTMENTS = new HashSet<Department>();
    private final Department dep10 = new Department(10, "ten");
    private final Department dep20 = new Department(20, "twenty");

    private void init() throws SQLException {
        clearAllTables();
        ALL_DEPARTMENTS.add(dep10);
        ALL_DEPARTMENTS.add(dep20);
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Employee knut = new Employee(1, "Knut", "Maier", dep10);
            Employee fred = new Employee(2, "Fred", "Schmidt", null);
            Cubicle green = new Cubicle(Integer.valueOf(1), Integer.valueOf(2), "green", knut);
            knut.setCubicle(green);
            em.persist(dep10);
            em.persist(dep20);
            em.persist(green);
            em.persist(knut);
            em.persist(fred);
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDefaultMapping() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNativeQuery("select * from TMP_DEP D where D.ID = 10", Department.class);
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDefaultMappingWithMappingResult() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNativeQuery("select * from TMP_DEP D where D.ID = 10", "departmentByClass");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDefaultMappingNamedNativeQuery() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNamedQuery("getDepartmentWithId10SQL_class");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testResultSetMappingNamedNativeQuery() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNamedQuery("getDepartmentWithId10SQL_mapping");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Skip(databases=SQLServerPlatform.class)
    @Test
    public void testColumnResult() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNamedQuery("getDepartmentName");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object != null, "object is null");
            verify("ten".equals(object), "wrong object: " + object);
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Skip(databases=SQLServerPlatform.class)
    @Test
    public void testFieldResult() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNamedQuery("getDepartmentFieldByField");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testDefaultMappingWithParameter() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Query query = em.createNativeQuery("select * from TMP_DEP D where D.ID = ?", Department.class);
            query.setParameter(1, Integer.valueOf(10));
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Department, "wrong instance: " + object.getClass().getName());
            verify(em.contains(object), "object not contained in em");
            Department department = (Department) object;
            verify(department.getId() == 10, "wrong id: " + department.getId());
            verify(!iter.hasNext(), "too many rows");
            getEnvironment().rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Skip(databases=SQLServerPlatform.class)
    @Test
    public void testFieldByField() throws SQLException {
        clearAllTables();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            getEnvironment().beginTransaction(em);
            Department dep1 = new Department(1, "one");
            Department dep2 = new Department(2, "two");
            em.persist(dep1);
            em.persist(dep2);
            getEnvironment().commitTransactionAndClear(em);
            Query query = em.createNamedQuery("getDepartmentFieldByField1");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "no results");
            Object object = iter.next();
            verify(object instanceof Object[], "wrong instance: " + object.getClass().getName());
            Object[] objects = (Object[]) object;
            verify(objects.length == 2, "wrong length: " + objects.length);
            verify(((Number) objects[0]).intValue() == 1, "wrong id: " + ((Number) objects[0]).intValue());
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }
}
