package bitronix.examples.hibernate;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.UserTransaction;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import bitronix.examples.hibernate.entities.User;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.resource.jdbc.PoolingDataSource;


public class Test {
	
	private static UserTransaction userTransaction;
    private static int nbTuples = 10;

	public static void main(String[] args) throws Exception {
		initDataSources();
		initTransactionManager();
		SessionFactory sf = new Configuration().configure("/hibernate1.cfg.xml").buildSessionFactory();
        userTransaction.begin();
		populateDB(sf);
        userTransaction.commit();
        
        userTransaction.begin();
        loopCountQuery(sf);
        userTransaction.commit();
		
		sf.close();
	
		
		System.out.println("END bru");
	}

	private static void populateDB(SessionFactory sf) {
        Session session = sf.getCurrentSession();
        /* Add nbTuples users*/
        for(int i = 0; i <= nbTuples; i++){
            User u = new User();
            u.setName("username "+i);
            session.save(u);
        }  
    }
    
    private static void loopCountQuery(SessionFactory sf){
        Session session = sf.getCurrentSession();
        for(int i = 0; i <= nbTuples; i++){
            double nb = Double.valueOf(String.valueOf((Integer) session.createCriteria(User.class)
                                                      .add(Restrictions.eq("name", "username "+i))
                                                      .setProjection(Projections.rowCount())
                                                      .uniqueResult()));
            System.out.println("User: usernaem "+i+" = "+nb);
        }
    }


	/**
	 * Initialize the transaction manager.
	 */
	private static void initTransactionManager() {
		userTransaction = TransactionManagerServices.getTransactionManager();
	}

	/**
	 * Create the datasource and it into the embedded JNDI server.
	 */
	private static void initDataSources() throws NamingException {
		Context ctx = new InitialContext();
		ctx.createSubcontext("jdbc");
		PoolingDataSource dataSource1 = getDataSource_db();
		ctx.rebind("jdbc/testDS1", dataSource1);
	}

	/**
	 * Create the first datasource.
	 */
	private static PoolingDataSource getDataSource_db() {
        
        /* Uncomment this to have the Last Resource Commit implementation */
        
//        PoolingDataSource ds = new PoolingDataSource();
//        ds.setUniqueName("jdbc/testDS1");
//        ds.setClassName("bitronix.tm.resource.jdbc.lrc.LrcXADataSource");
//        ds.setMaxPoolSize(3);
//        ds.setAllowLocalTransactions(true);
//        ds.getDriverProperties().setProperty("driverClassName", "org.postgresql.Driver");
//        ds.getDriverProperties().setProperty("url", "jdbc:postgresql://127.0.0.1:5432/test");
//        ds.getDriverProperties().put("user", "hibernate");
//        ds.getDriverProperties().put("password", "hibernate");
//        
//        ds.init();
//        return ds;
        
		PoolingDataSource ds = new PoolingDataSource();
		ds.setUniqueName("jdbc/testDS1");
		ds.setClassName("org.postgresql.xa.PGXADataSource");
		ds.setMaxPoolSize(3);
		ds.getDriverProperties().put("databaseName", "test");
        ds.getDriverProperties().put("user", "hibernate");
        ds.getDriverProperties().put("password", "hibernate");
        ds.getDriverProperties().put("serverName", "127.0.0.1");
        ds.getDriverProperties().put("portNumber", "5432");
        
		ds.init();
		return ds;
    }
}
