/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.api.metadata.view.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import junit.textui.TestRunner;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import com.jaspersoft.jasperserver.api.metadata.common.domain.Folder;
import com.jaspersoft.jasperserver.api.metadata.common.service.impl.hibernate.persistent.RepoFolder;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.impl.RepoReportUnit;
import com.jaspersoft.jasperserver.api.metadata.user.domain.User;
import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoRole;
import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoTenant;
import com.jaspersoft.jasperserver.api.metadata.user.domain.impl.hibernate.RepoUser;
import com.jaspersoft.jasperserver.api.metadata.user.service.TenantService;
import com.jaspersoft.jasperserver.util.test.BaseJasperServerTest;


/**
 * @author swood
 * @version $Id: HibernateAccessTest.java 19930 2010-12-11 15:17:19Z tmatyashovsky $
 */
public class HibernateAccessTest extends BaseJasperServerTest {

	public static int NUMBER_OF_TEST_ROLES = 5;

	SessionFactory sessionFactory;
	RepoReportUnit testObject;
	RepoFolder root;
	HibernateTemplate template;
	HibernateDaoSupport jasperServerDao;
	
    private Properties jdbcProps;

	User testUser;
	List testRoles = new ArrayList(NUMBER_OF_TEST_ROLES);
    Long testTenantId;
    
	public HibernateDaoSupport getJasperServerDao() {
		return jasperServerDao;
	}

	public void setJasperServerDao(HibernateDaoSupport jasperServerDao) {
		this.jasperServerDao = jasperServerDao;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public HibernateAccessTest(String name) {
		super(name);
		setAutowireMode(AUTOWIRE_BY_NAME);
	}

	public static void main(String[] args) {
		TestRunner.run(HibernateAccessTest.class);
	}
    
	protected void onSetUp() throws Exception {
		System.out.println("Setup HibernateAccessTest");


		/*
		 * The TransactionSynchronizationManager work is only needed in tests to allow multiple
		 * Hibernate transactions to occur. Otherwise, each "template." call is a transaction.
		 * Lazy initialization of collections will not occur otherwise. In a web app, there is Spring
		 * configuration to do a transaction per web request - OpenSessionInViewFilter.
		 */
		Session s = sessionFactory.openSession();

		TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

		template = jasperServerDao.getHibernateTemplate();

		// TODO: root folder needs to be here for other unit-test suites to run

		//we need to create a folder because RepoResource.parent is not nullable
		final RepoFolder root = new RepoFolder();
		root.setCreationDate(new Date());
		root.setUpdateDate(new Date());
		root.setName(Folder.SEPARATOR);
		root.setLabel("root");
		root.setDescription("Root of the folder hierarchy");
		root.setURI(Folder.SEPARATOR);
		root.setHidden(false);
		root.setParent(null);
		template.save(root);
	}

	public void onTearDown() {
		System.out.println("Tear down HibernateAccessTest");
		/*
		 *  Leave entries in the database
		 *
				if (testObject != null) {
					final ReportUnit testObjectDel = testObject;
					template.delete(testObjectDel);
				}
				if (testUser != null) {
					final User testObjectDel = testUser;
					template.delete(testObjectDel);
				}
				if (testRoles != null) {
					Iterator it = testRoles.iterator();
					while (it.hasNext()) {
						final Role testObjectDel = (Role) it.next();
						template.delete(testObjectDel);
					}
				}
		*/

		SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);

		Session s = holder.getSession();

		s.flush();
		TransactionSynchronizationManager.unbindResource(sessionFactory);
		SessionFactoryUtils.releaseSession(s, sessionFactory);
	}

	public void createReportUnit() throws Exception {
		System.out.println("createReportUnit");

		final RepoReportUnit testObjectImpl = new RepoReportUnit();
		testObjectImpl.setCreationDate(new Date());
		testObjectImpl.setDescription("Test");
		testObjectImpl.setName("Test");
		testObjectImpl.setLabel("Test");
		testObjectImpl.setParent(root);
		final Long testObjectId = (Long) template.save(testObjectImpl);
		assertNotNull("testObjectId", testObjectId);
		testObject = (RepoReportUnit) template.load(RepoReportUnit.class, testObjectId);
		assertNotNull("testObject", testObject);
	}

	public void createUser() throws Exception {
		System.out.println("createUser");
		final RepoUser testUserImpl = new RepoUser();
		testUserImpl.setUsername("TestUser");
		testUserImpl.setFullName("TestUser");
		testUserImpl.setPassword("newPassword");
		testUserImpl.setEnabled(true);
		testUserImpl.setExternallyDefined(false);

        RepoTenant defaultTenant = (RepoTenant) template.load(RepoTenant.class, testTenantId);
        testUserImpl.setTenant(defaultTenant);

		Long testObjectId = (Long) template.save(testUserImpl);
		testUser = (User) template.load(RepoUser.class, testObjectId);
		assertNotNull("testUser null", testUser);
	}

	public void createRoles() throws Exception {
		System.out.println("testCreateRoles");
		for (int i = 0; i < NUMBER_OF_TEST_ROLES; i++) {
			final RepoRole testRoleImpl = new RepoRole();
			String roleName = "TestRole" + i;
			testRoleImpl.setRoleName(roleName);
			testRoleImpl.setExternallyDefined(false);

            RepoTenant defaultTenant = (RepoTenant) template.load(RepoTenant.class, testTenantId);
            testRoleImpl.setTenant(defaultTenant);

			template.saveOrUpdate(testRoleImpl);

			testRoles.add(testRoleImpl);

			testUser.addRole(testRoleImpl);
		}

		template.saveOrUpdate(testUser);
		assertTrue("testUser.getRoles().size()", testUser.getRoles().size() == NUMBER_OF_TEST_ROLES);

	}
    
    public void createDefaultTenant() {
        System.out.println("createDefaultTenant");
        RepoTenant aTenant = new RepoTenant();
        aTenant.setTenantId(TenantService.ORGANIZATIONS);
        aTenant.setTenantAlias(TenantService.ORGANIZATIONS);
        aTenant.setParent(null);
        aTenant.setTenantName("root");
        aTenant.setTenantDesc("default tenant");
        aTenant.setTenantNote("");
        aTenant.setTenantUri("/");
        aTenant.setTenantFolderUri("/");
        testTenantId = (Long) template.save(aTenant);
    }

	public void disabled_testReportUnitQuery() throws Exception {

		createReportUnit();

		System.out.println("testQuery");
		List result = template.find("from RepoReportUnit where name = ?", "Test");
		assertNotNull("result", result);
		assertTrue("result.size() == 1", result.size() == 1);
		testObject = (RepoReportUnit) result.get(0);
	}

	public void testUserQuery() throws Exception {
        createDefaultTenant();
		createUser();
		createRoles();
		template.flush();

		System.out.println("testUserQuery");

		List result = template.find("from RepoUser where username = ?", "TestUser");

		assertNotNull("result", result);
		assertTrue("result.size() == 1",result.size() == 1);

		System.out.println("testUserQuery: found result OK");

		testUser = (User) result.get(0);
		assertNotNull("testUser", testUser);
		assertNotNull("testUser.getRoles()", testUser.getRoles());
		assertTrue("testUser.getRoles().size()", testUser.getRoles().size() == NUMBER_OF_TEST_ROLES);

		System.out.println("testUserQuery: roles OK");
	}

}
