PlaceBean.java 7.6 KB
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.insomnia.bortal.beans;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import fi.insomnia.bortal.enums.Permission;
import fi.insomnia.bortal.enums.RolePermission;
import fi.insomnia.bortal.exceptions.BortalCatchableException;
import fi.insomnia.bortal.exceptions.PermissionDeniedException;
import fi.insomnia.bortal.facade.GroupMembershipFacade;
import fi.insomnia.bortal.facade.PlaceFacade;
import fi.insomnia.bortal.facade.PlaceGroupFacade;
import fi.insomnia.bortal.model.EventMap;
import fi.insomnia.bortal.model.GroupMembership;
import fi.insomnia.bortal.model.LanEvent;
import fi.insomnia.bortal.model.Place;
import fi.insomnia.bortal.model.PlaceGroup;
import fi.insomnia.bortal.model.Product;
import fi.insomnia.bortal.model.User;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.persistence.RollbackException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author tuukka
 */
@Stateless
public class PlaceBean implements PlaceBeanLocal {
    private static final String PLACE_RESERVE_TIMEOUTER = "Map reserve timeouter";
    private static final Logger logger = LoggerFactory.getLogger(PlaceBean.class);
    @EJB
    private GroupMembershipFacade gmemfacade;
    @Resource
    private TimerService ts;

    @EJB
    private PlaceFacade placeFacade;

    @EJB
    private PlaceGroupFacade pgfacade;
    @EJB
    private UserBeanLocal userbean;

    @EJB
    private ProductBeanLocal productBean;

    @EJB
    private EventBeanLocal eventBean;

    @EJB
    private PlaceGroupBeanLocal pgbean;

    @EJB
    private SecurityBeanLocal secubean;
    @EJB
    private EventMapBeanLocal mapfacade;

    @Override
    public Place mergeChanges(Place place) {
        userbean.fatalPermission(Permission.MAP, RolePermission.WRITE, "User tried to modify place ", place);
        return placeFacade.merge(place);
    }

    @Override
    public BigDecimal totalReservationPrice(EventMap e, Place newPlace) {

        Set<Place> places = new HashSet<Place>();
        places.addAll(placeFacade.findUsersReservations(e, userbean.getCurrentUser()));

        if (newPlace != null) {
            places.add(newPlace);
        }

        Map<Product, Integer> mockmap = getPlaceProductcount(places);

        BigDecimal total = BigDecimal.ZERO;

        for (Entry<Product, Integer> entry : mockmap.entrySet()) {
            logger.debug("Adding to price {} of {}", entry.getValue(), entry.getKey().getName());
            if (entry.getKey() != null) {
                total = total.add(productBean.calculateTotal(entry.getKey(), new BigDecimal(entry.getValue())));
            }
        }
        return total;
    }

    private static Map<Product, Integer> getPlaceProductcount(Collection<Place> places) {
        HashMap<Product, Integer> mockmap = new HashMap<Product, Integer>();

        for (Place p : places) {
            if (p != null) {
                Product prod = p.getProduct();
                Integer val = mockmap.get(prod);
                if (val == null) {
                    val = 0;
                }
                mockmap.put(prod, ++val);
            }
        }

        return mockmap;

    }

    // TODO: Kantakysely tähän!
    @Override
    public Place findPlace(EventMap e, int x, int y) {
        for (Place place : e.getPlaces()) {
            if (place.isCoordinateInPlace(x, y)) {
                return place;
            }
        }
        return null;

    }

    @Override
    public boolean reservePlace(Place p, User user) {
        userbean.fatalPermission(Permission.MAP, RolePermission.EXECUTE, "User does not have rights to reserve ( and buy) a place");
        boolean ret = placeFacade.reservePlace(p, user);

        boolean foundTimeout = false;
        for (Timer t : ts.getTimers()) {
            if (t.getInfo().equals(PLACE_RESERVE_TIMEOUTER)) {
                foundTimeout = true;
            }
        }
        if (!foundTimeout) {
            logger.info("Place timeout calculator not started. Starting new.");
            ts.createTimer(new Date(), 1000 * 60, PLACE_RESERVE_TIMEOUTER);
        }
        return ret;
    }

    @Timeout
    public void checkTimedOutPlaces(Timer timer) {
        // logger.debug("Checking Timed out places at {}", new Date());
        placeFacade.timeoutPlaces();
    }

    @Override
    public void releaseUsersPlaces() {
        logger.debug("timeouting places");
        placeFacade.releasePlaces(userbean.getCurrentUser());
    }

    @Override
    public boolean releasePlace(Place place, User user) {
        return placeFacade.releasePlace(user, place);

    }

    @Override
    public boolean buySelectedPlaces(EventMap e) throws BortalCatchableException {
        userbean.fatalPermission(Permission.MAP, RolePermission.EXECUTE, "User does not have rights to reserve ( and buy) a place");
        LanEvent event = eventBean.getCurrentEvent();
        User user = userbean.getCurrentUser();

        List<Place> places = placeFacade.findUsersReservations(e, user);
        if (places.size() <= 0) {
            return false;
        }
        PlaceGroup pg = new PlaceGroup(event, Calendar.getInstance(), Calendar.getInstance(), true);
        pg.setCreator(user);
        pgfacade.create(pg);

        // PlaceGroup pg = pgbean.createPlaceGroup(user);
        BigDecimal totalprice = totalReservationPrice(e, null);
        BigDecimal balance = userbean.getCurrentUser().getAccountBalance();
        if (balance.compareTo(totalprice) < 0) {
            logger.debug("User {} Could not buy things because account balance is too low!", user);
            return false;
        }

        for (Place p : places) {
            if (!p.buy(pg)) {
                throw new BortalCatchableException("Error while buying places");
            }
            placeFacade.merge(p);
            GroupMembership membership = new GroupMembership(event, pg, p, gmemfacade.createInviteToken(event));
            pg.getMembers().add(membership);
        }

        for (Entry<Product, Integer> line : getPlaceProductcount(places).entrySet()) {
            productBean.createAccountEvent(line.getKey(), new BigDecimal(line.getValue()), user);
        }
        return true;
    }

    @Override
    public void lockPlaces(User user, Product prod, BigDecimal quantity) {
        BigDecimal loop = BigDecimal.ZERO;
        LanEvent event = eventBean.getCurrentEvent();
        PlaceGroup pg = new PlaceGroup(event, Calendar.getInstance(), Calendar.getInstance(), true);
        pg.setCreator(user);
        pgfacade.create(pg);
        for (Place p : prod.getPlaces()) {

            if (!p.isTaken()) {
                p.reserve(user);
                p.buy(pg);

                pg.getMembers().add(new GroupMembership(event, pg, p, gmemfacade.createInviteToken(event)));
                placeFacade.merge(p);
                // pgbean.createGroupMembership(pg, p);
                loop = loop.add(BigDecimal.ONE);
                if (loop.compareTo(quantity) >= 0) {
                    break;
                }
            }
        }
    }

    @Override
    public int setBuyable(EventMap map, String like, boolean b) {
        userbean.fatalPermission(Permission.MAP, RolePermission.WRITE, "User tried to change place buyable: " + like + " to " + b);
        return placeFacade.setBuyable(map, like, b);

    }

}