/**
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 -
 - JASS: Java Advanced tranSaction Support
 -
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 -
 - This module was originally developed by 
 -
 -    LSD (Distributed Systems Lab, http://lsd.ls.fi.upm.es/lsd/lsd.htm)
 -    at Universidad Politecnica de Madrid (UPM) as an ObjectWeb Consortium
 -    (http://www.objectweb.org) project.
 -
 -    This project has been partially funded by the European Commission under
 -    the IST programme of V FP grant IST-2001-37126 and by the Spanish
 -    Ministry of Science & Technology (MCyT) grants TIC2002-10376-E and
 -    TIC2001-1586-C03-02
 -
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 -  The original code and portions created by LSD are 
 -  Copyright (c) 2004 LSD (UPM)  
 -  All rights reserved.
 -  
 - Redistribution and use in source and binary forms, with or without 
 - modification, are permitted provided that the following conditions are met:
 -
 - -Redistributions of source code must retain the above copyright notice, this
 - list of conditions and the following disclaimer. 
 -
 - -Redistributions in binary form must reproduce the above copyright notice, 
 - this list of conditions and the following disclaimer in the documentation 
 - and/or other materials provided with the distribution. 
 -
 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 - POSSIBILITY OF SUCH DAMAGE.
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 -
 -  Author: Francisco Perez Sorrosal (frperezs)
 -
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/

package org.objectweb.jass.examples.travelagency.ejbs;

import org
	.objectweb
	.jass
	.examples
	.travelagency
	.exceptions
	.NotEnoughSeatsException;
import org
	.objectweb
	.jass
	.examples
	.travelagency
	.ejbs
	.compensations
	.ReserveSeatsCompensation;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.activity.opennested.UserOpenNested;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Makes the seats reservation.
 * It creates a ONT activity through the OpenNested service when methods that
 * perform db changes are invoked (reserveSeats(), unreserveSeats()). 
 * @author fran
 * Date: Feb 16, 2004
 * org.objectweb.jass.examples.travelagency.ejbsAirlineBean.java
 */
public class AirlineBean implements SessionBean {
	public AirlineBean() {
	}

	public void ejbCreate() throws javax.ejb.CreateException {
	}

	public void ejbActivate() throws EJBException {
	}

	public void ejbPassivate() throws EJBException {
	}

	public void ejbRemove() throws EJBException {
	}

	public void setSessionContext(SessionContext sessionContext)
		throws EJBException {
	}

	/**
	 * Obtains the number of free seats.
	 * @return - the number of free seats.
	 */
	public int getFreeSeats() throws SQLException {
		int seats = -1;

		Context ctx = null;
		try {
			ctx = new InitialContext();
			DataSource ds = null;
			ds = (DataSource) ctx.lookup("java:/AdaptAirlineDS");
			Connection c = ds.getConnection();
			Statement stmt = c.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT seats FROM flights");
			if (rs.next()) {
				seats = rs.getInt(1);
			}
			rs.close();
			stmt.close();
			c.close();
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			throw e;
		}
		return seats;
	}

	/**
	 * Performs the seats reservation. If there are not enough seats, it throws
	 * the NotEnoughSeatsException.
	 * @param nSeats - the number of seats to reserve.
	 * @return
	 * @throws NotEnoughSeatsException - thown if there are not enough seats.
	 */
	public int reserveSeats(int nSeats) throws NotEnoughSeatsException, SQLException {
		UserOpenNested uon = getUserOpenNested();
		try {
			uon.activityBegin(0);
			Context ctx = new InitialContext();
			DataSource ds = (DataSource) ctx.lookup("java:/AdaptAirlineDS");
			Connection c = ds.getConnection();
			Statement stmt = c.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT seats FROM flights");
			int freeSeats = 0;
			rs.next();
			freeSeats = rs.getInt(1);
			if ((freeSeats - nSeats) < 0) {
				uon.activityRollback();
				rs.close();
				stmt.close();
				c.close();
				throw new NotEnoughSeatsException();
			} else {
				stmt.executeUpdate(
					"UPDATE flights SET seats = " + (freeSeats - nSeats));
				ReserveSeatsCompensation compensation =
					new ReserveSeatsCompensation(this, nSeats);
				uon.activityCommit(compensation);
			}
			rs.close();
			stmt.close();
			c.close();
		} catch (SQLException e) {
			try {
				uon.activityRollback();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			throw e;
		} catch (NotEnoughSeatsException e) {
			throw e;
		} catch(Exception e) {
			e.printStackTrace();
		}
		return nSeats;
	}

	/**
	 * Performs the compensation for the reserveSeats() operation.
	 * @param nSeats - the number of seats to cancel.
	 * @return
	 */
	public int unreserveSeats(int nSeats) throws SQLException {
		UserOpenNested uon = getUserOpenNested();
		try {
			uon.activityBegin(0);
			Context ctx = new InitialContext();
			DataSource ds = (DataSource) ctx.lookup("java:/AdaptAirlineDS");
			Connection c = ds.getConnection();
			Statement stmt = c.createStatement();
			ResultSet rs = stmt.executeQuery("SELECT seats FROM flights");
			int freeSeats = 0;
			rs.next();
			freeSeats = rs.getInt(1);
			stmt.executeUpdate(
				"UPDATE flights SET seats = " + (freeSeats + nSeats));
			uon.activityCommit(null);
			rs.close();
			stmt.close();
			c.close();		
		} catch (SQLException e) {
			try {
				uon.activityRollback();
			} catch (Exception e1) {				
				e1.printStackTrace();
			}
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 0;
	}

	/**
	* Gets the reference to the UserOpenNested service.
	*/
	private UserOpenNested getUserOpenNested() {
		UserOpenNested uon = null;
		Context ctx = null;

		try {
			ctx = new InitialContext();
			uon = (UserOpenNested) ctx.lookup("UserOpenNested");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return uon;
	}
}
