PlaceFacade.java 9.08 KB
/*
 * Copyright Codecrew Ry
 * 
 * All rights reserved.
 * 
 * This license applies to any software containing a notice placed by the 
 * copyright holder. Such software is herein referred to as the Software. 
 * This license covers modification, distribution and use of the Software. 
 * 
 * Any distribution and use in source and binary forms, with or without 
 * modification is not permitted without explicit written permission from the 
 * copyright owner. 
 * 
 * A non-exclusive royalty-free right is granted to the copyright owner of the 
 * Software to use, modify and distribute all modifications to the Software in 
 * future versions of the Software. 
 * 
 */
package fi.codecrew.moya.facade;

import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;

import fi.codecrew.moya.beans.EventBean;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.LoggingBeanLocal;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;

@Stateless
@LocalBean
public class PlaceFacade extends IntegerPkGenericFacade<Place> {

	private static final Logger logger = LoggerFactory.getLogger(PlaceFacade.class);

	@EJB
	private EventBean eventBean;

	@EJB
	private PlaceSlotFacade placeslotfacade;

	@EJB
	private LoggingBeanLocal logbean;

	public PlaceFacade() {

		super(Place.class);
	}

	@Override
	public Place find(Integer id) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);

		Root<Place> root = cq.from(Place.class);

		cq.where(
				cb.equal(root.get(Place_.id), id),
				cb.equal(root.get(Place_.map).get(EventMap_.event), eventBean.getCurrentEvent())
				);
		return super.getSingleNullableResult(getEm().createQuery(cq));
	}

	public void timeoutPlaces() {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);

		Root<Place> root = cq.from(Place.class);

		cq.select(root);
		cq.where(cb.lessThan(root.get(Place_.releaseTime), Calendar.getInstance()),
				cb.isNull(root.get(Place_.group)));

		TypedQuery<Place> q = getEm().createQuery(cq);

		int updated = 0;
		for (Place p : q.getResultList()) {
			logger.debug("Releasing place {} at automagic timed place check.", p);
			final EventUser cu = p.getCurrentUser();
			if (p.checkReleased()) {
				PlaceSlot slot = placeslotfacade.findSlotForPlace(p);

				if (slot != null) {
					slot.setPlace(null);
					slot.setUsed(null);
				}
				logbean.sendMessage(MoyaEventType.PLACE_ERROR, cu, "Automatically release unlocked place ", p.getName());
				++updated;
			}
		}

		if (updated > 0) {
			logger.info("{} places released for sale after release time exceeded.", updated);
		}
	}

	public List<Place> findUsersReservations(LanEvent event, EventUser user) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);

		Root<Place> root = cq.from(Place.class);

		cq.select(root);
		cq.where(
				cb.and(
						cb.equal(root.get(Place_.map).get(EventMap_.event), event),
						cb.equal(root.get(Place_.currentUser), user)
						));
		TypedQuery<Place> q = getEm().createQuery(cq);

		return q.getResultList();
	}

	public List<Place> findUsersUnlocketSelected(EventUser user) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);

		Root<Place> root = cq.from(Place.class);

		cq.select(root);
		cq.where(
				cb.and(
						cb.equal(root.get(Place_.map).get(EventMap_.event), user.getEvent()),
						cb.equal(root.get(Place_.currentUser), user),
						cb.isNull(root.get(Place_.group))
						));
		TypedQuery<Place> q = getEm().createQuery(cq);

		return q.getResultList();
	}

	public int setBuyable(EventMap map, String like, boolean b) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);
		Root<Place> root = cq.from(Place.class);
		cq.where(
				cb.like(root.get(Place_.name), like),
				cb.equal(root.get(Place_.map), map)
				);

		List<Place> list = getEm().createQuery(cq).getResultList();
		for (Place p : list) {
			p.setBuyable(b);
		}

		// Query q =
		// em.createQuery("UPDATE Place p set p.buyable = :b where p.name like :like");
		// q.setParameter("b", b);
		// q.setParameter("like", like);
		return list.size();

	}

	// public boolean isCoordinateInPlace(int x, int y) {
	// if (x > mapX
	// && x < (mapX + width)
	// && y > mapY
	// && y < (mapY + height)) {
	// return true;
	// }
	//
	// return false;
	// }
	public Place find(EventMap map, int x, int y) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);
		Root<Place> root = cq.from(Place.class);
		Path<Integer> xObj = root.get(Place_.mapX);
		Path<Integer> yObj = root.get(Place_.mapY);

		cq.where(cb.equal(root.get(Place_.map), map),
				cb.lessThan(xObj, x),
				cb.greaterThan(cb.sum(xObj, root.get(Place_.width)), x),
				cb.lessThan(yObj, y),
				cb.greaterThan(cb.sum(yObj, root.get(Place_.height)), y),
				cb.isFalse(root.get(Place_.disabled))
				);
		return getSingleNullableResult(getEm().createQuery(cq));
	}

	public List<Place> findAll() {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Place> cq = cb.createQuery(Place.class);
		Root<Place> root = cq.from(Place.class);
		cq.where(cb.equal(root.get(Place_.map).get(EventMap_.event), eventBean.getCurrentEvent()));
		cq.orderBy(cb.asc(root.get(Place_.name)));
		return getEm().createQuery(cq).getResultList();
	}

	public Long countSelectable(Product product) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery(Long.class);
		Root<Place> root = cq.from(Place.class);
		cq.select(cb.count(root));

		cq.where(
				cb.equal(root.get(Place_.product), product),
				cb.isNull(root.get(Place_.releaseTime)),
				cb.isNull(root.get(Place_.group)),
				cb.isFalse(root.get(Place_.disabled)),
				cb.isTrue(root.get(Place_.buyable))
				);
		return super.getSingleNullableResult(getEm().createQuery(cq));
	}

	public Long findCountForProduct(Product product) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery(Long.class);
		Root<Place> root = cq.from(Place.class);
		cq.select(cb.count(root));

		cq.where(
				cb.equal(root.get(Place_.product), product),
				cb.isFalse(root.get(Place_.disabled))
				);
		return super.getSingleNullableResult(getEm().createQuery(cq));
	}

	public Long countAvailable(EventMap map) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery(Long.class);

		Root<Place> root = cq.from(Place.class);

		cq.select(cb.count(root));

		cq.where(
				cb.equal(root.get(Place_.map), map),
				cb.isFalse(root.get(Place_.disabled)),

				// TKwtf lisäsi:
				cb.isTrue(root.get(Place_.buyable))
				);

		return getSingleNullableResult(getEm().createQuery(cq));

	}

	public Long countSelectable(EventMap map) {

		if (map == null) {
			return null;
		}

		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery(Long.class);

		Root<Place> root = cq.from(Place.class);

		cq.select(cb.count(root));

		cq.where(
				cb.equal(root.get(Place_.map), map),
				cb.isNull(root.get(Place_.releaseTime)),
				cb.isNull(root.get(Place_.group)),
				cb.isFalse(root.get(Place_.disabled)),
				// TKwtf lisäsi:
				cb.isTrue(root.get(Place_.buyable))

				);

		return getSingleNullableResult(getEm().createQuery(cq));
	}

	public List<Product> getMapProducts(EventMap map) {

		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Product> cq = cb.createQuery(Product.class);

		Root<Product> root = cq.from(Product.class);
		Subquery<Integer> subq = cq.subquery(Integer.class);
		Root<Place> subroot = subq.from(Place.class);
		subq.select(subroot.get(Place_.product).get(Product_.id));
		subq.distinct(true);
		subq.where(cb.equal(subroot.get(Place_.map), map));

		cq.where(root.get(Product_.id).in(subq));

		return getEm().createQuery(cq).getResultList();
	}

	public List<Product> getPlaceProducts() {

		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Product> cq = cb.createQuery(Product.class);
		Root<Product> root = cq.from(Product.class);

		Subquery<Integer> subq = cq.subquery(Integer.class);

		Root<Product> subroot = subq.from(Product.class);
		subq.select(subroot.get(Product_.id));
		subq.distinct(true);

		Join<Product, Place> placeJoin = subroot.join(Product_.places);

		subq.where(
				placeJoin.get(Place_.id).isNotNull(),
				cb.equal(placeJoin.get(Place_.map).get(EventMap_.event), eventBean.getCurrentEvent())
		);


		ProductFlag[] flags = {ProductFlag.CREATE_NEW_PLACE_WHEN_BOUGHT};

		cq.where(
				cb.or(
						root.get(Product_.id).in(subq),
						root.get(Product_.productFlags).in(Arrays.asList(flags))
				),
				cb.equal(root.get(Product_.event), eventBean.getCurrentEvent())
		);

		cq.orderBy(cb.asc(root.get(Product_.name)));

		return getEm().createQuery(cq).getResultList();
	}
}