content: /*******************************************************************************
  * Copyright (c) 2013-2015 IBM Corp.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *******************************************************************************/
  package com.acmeair.wxs.service;
  
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  import javax.annotation.PostConstruct;
  import javax.inject.Inject;
  
  import com.acmeair.entities.Booking;
  import com.acmeair.entities.Customer;
  import com.acmeair.entities.Flight;
  import com.acmeair.service.BookingService;
  import com.acmeair.service.CustomerService;
  import com.acmeair.service.DataService;
  import com.acmeair.service.FlightService;
  import com.acmeair.service.KeyGenerator;
  import com.acmeair.service.ServiceLocator;
  import com.acmeair.wxs.WXSConstants;
  import com.acmeair.wxs.entities.BookingImpl;
  import com.acmeair.wxs.entities.BookingPKImpl;
  import com.acmeair.wxs.entities.FlightPKImpl;
  import com.acmeair.wxs.utils.WXSSessionManager;
  import com.ibm.websphere.objectgrid.ObjectGrid;
  import com.ibm.websphere.objectgrid.ObjectGridException;
  import com.ibm.websphere.objectgrid.ObjectMap;
  import com.ibm.websphere.objectgrid.Session;
  import com.ibm.websphere.objectgrid.UndefinedMapException;
  import com.ibm.websphere.objectgrid.plugins.TransactionCallbackException;
  import com.ibm.websphere.objectgrid.plugins.index.MapIndex;
  
  
  @DataService(name=WXSConstants.KEY,description=WXSConstants.KEY_DESCRIPTION)
  public class BookingServiceImpl implements BookingService, WXSConstants  {
  	
  	private final static Logger logger = Logger.getLogger(BookingService.class.getName()); 
  	
  	private static String BOOKING_MAP_NAME="Booking";
  	private static String BASE_BOOKING_MAP_NAME="Booking";
  
  	private ObjectGrid og;
  	
  	@Inject
  	private KeyGenerator keyGenerator;
  	
  	private FlightService flightService = ServiceLocator.instance().getService(FlightService.class);
  	private CustomerService customerService = ServiceLocator.instance().getService(CustomerService.class);
  	
  	
  	@PostConstruct
  	private void initialization()  {
  		try {
  			og = WXSSessionManager.getSessionManager().getObjectGrid();
  			BOOKING_MAP_NAME = BASE_BOOKING_MAP_NAME + WXSSessionManager.getSessionManager().getMapSuffix();
  		} catch (ObjectGridException e) {
  			logger.severe("Unable to retreive the ObjectGrid reference " + e.getMessage());
  		}
  	}
  	
  		
  	public BookingPKImpl bookFlight(String customerId, FlightPKImpl flightId) {
  		try{
  			// We still delegate to the flight and customer service for the map access than getting the map instance directly
  			Flight f = flightService.getFlightByFlightId(flightId.getId(), flightId.getFlightSegmentId());
  			Customer c = customerService.getCustomerByUsername(customerId);
  			
  			BookingImpl newBooking = new BookingImpl(keyGenerator.generate().toString(), new Date(), c, f);
  			BookingPKImpl key = newBooking.getPkey();
  			
  			//Session session = sessionManager.getObjectGridSession();
  			Session session = og.getSession();
  			ObjectMap bookingMap = session.getMap(BOOKING_MAP_NAME);
  			@SuppressWarnings("unchecked")
  			HashSet<Booking> bookingsByUser = (HashSet<Booking>)bookingMap.get(customerId);
  			if (bookingsByUser == null) {
  				bookingsByUser = new HashSet<Booking>();
  			}
  			if (bookingsByUser.contains(newBooking)) {
  				throw new Exception("trying to book a duplicate booking");
  			}
  			bookingsByUser.add(newBooking);
  			bookingMap.upsert(customerId, bookingsByUser);
  			return key;
  		}catch (Exception e)
  		{
  			throw new RuntimeException(e);
  		}
  	}
  
  	@Override
  	public String bookFlight(String customerId, String flightSegmentId, String id) {
  		if(logger.isLoggable(Level.FINER))
  			logger.finer("WXS booking service,  bookFlight with customerId = '"+ customerId+"', flightSegmentId = '"+ flightSegmentId + "',  and id = '" + id + "'");
  		return bookFlight(customerId, new FlightPKImpl(flightSegmentId, id)).getId();
  	}
  	
  	@Override
  	public Booking getBooking(String user, String id) {
  		
  		try{
  			//Session session = sessionManager.getObjectGridSession();
  			Session session = og.getSession();
  			ObjectMap bookingMap = session.getMap(BOOKING_MAP_NAME);
  			
  //			return (Booking)bookingMap.get(new BookingPK(user, id));
  			@SuppressWarnings("unchecked")
  			HashSet<BookingImpl> bookingsByUser = (HashSet<BookingImpl>)bookingMap.get(user);
  			if (bookingsByUser == null) {
  				return null;
  			}
  			for (BookingImpl b : bookingsByUser) {
  				if (b.getPkey().getId().equals(id)) {
  					return b;
  				}
  			}
  			return null;
  
  		}catch (Exception e)
  		{
  			throw new RuntimeException(e);
  		}
  			
  	}
  
  	@Override
  	public void cancelBooking(String user, String id) {
  		try{
  			Session session = og.getSession();
  			//Session session = sessionManager.getObjectGridSession();
  			ObjectMap bookingMap = session.getMap(BOOKING_MAP_NAME);
  			@SuppressWarnings("unchecked")
  			HashSet<BookingImpl> bookingsByUser = (HashSet<BookingImpl>)bookingMap.get(user);
  			if (bookingsByUser == null) {
  				return;
  			}
  			boolean found = false;
  			HashSet<Booking> newBookings = new HashSet<Booking>();
  			for (BookingImpl b : bookingsByUser) {
  				if (b.getPkey().getId().equals(id)) {
  					found = true;
  				}
  				else {
  					newBookings.add(b);
  				}
  			}
  			
  			if (found) {
  				bookingMap.upsert(user, newBookings);
  			}
  		}catch (Exception e)
  		{
  			throw new RuntimeException(e);
  		}
  	}		
  	
  	@Override
  	public List<Booking> getBookingsByUser(String user) {
  		try{
  			Session session = og.getSession();
  			//Session session = sessionManager.getObjectGridSession();
  	
  			boolean startedTran = false;
  			if (!session.isTransactionActive()) {
  				startedTran = true;
  				session.begin();
  			}
  			
  			ObjectMap bookingMap = session.getMap(BOOKING_MAP_NAME);
  			@SuppressWarnings("unchecked")
  			HashSet<Booking> bookingsByUser = (HashSet<Booking>)bookingMap.get(user);
  			if (bookingsByUser == null) {
  				bookingsByUser = new HashSet<Booking>();
  			}
  			
  			ArrayList<Booking> bookingsList = new ArrayList<Booking>();
  			for (Booking b : bookingsByUser) {
  				bookingsList.add(b);
  			}
  		
  			if (startedTran)
  				session.commit();
  			
  			return bookingsList;
  		}catch (Exception e)
  		{
  			throw new RuntimeException(e);
  		}
  		
  	}
  	
  	@Override
  	public Long count () {
  		try {
  			Session session = og.getSession();
  			ObjectMap objectMap = session.getMap(BOOKING_MAP_NAME);			
  			MapIndex mapIndex = (MapIndex)objectMap.getIndex("com.ibm.ws.objectgrid.builtin.map.KeyIndex");			
  			Iterator<?> keyIterator = mapIndex.findAll();
  			Long result = 0L;
  			while(keyIterator.hasNext()) {
  				keyIterator.next(); 
  				result++;
  			}
  			/*
  			int partitions = og.getMap(BOOKING_MAP_NAME).getPartitionManager().getNumOfPartitions();
  			Long result = 0L;
  			ObjectQuery query = og.getSession().createObjectQuery("SELECT COUNT ( o ) FROM " + BOOKING_MAP_NAME + " o ");
  			for(int i = 0; i<partitions;i++){
  				query.setPartition(i);
  				result += (Long) query.getSingleResult();
  			}
  			*/			
  			return result;
  		} catch (UndefinedMapException e) {
  			e.printStackTrace();
  		} catch (TransactionCallbackException e) {
  			e.printStackTrace();
  		} catch (ObjectGridException e) {
  			e.printStackTrace();
  		}	
  		return -1L;
  	}
  }
  