Commit fb37e3fb by Tuukka Kivilahti

Merge branch 'queue' into 'master'

Queue

Queue ugly, but working version

See merge request !154
2 parents 860a76c0 99309154
package fi.codecrew.moya.beans;
import javax.ejb.Local;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
@Local
public interface QueueBeanLocal {
MapReservationQueueEntry enterQueue(EventMap map, EventUser user);
boolean isReserving(EventMap map, EventUser user);
Integer getQueuePosition(EventMap map, EventUser user);
boolean isQueueEnabled();
MapReservationQueueEntry remove(EventMap map, EventUser user);
}
package fi.codecrew.moya.beans;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
import javax.ejb.Asynchronous;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEventProperty;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
/**
* Session Bean implementation class QueueBean
*/
@Singleton
@LocalBean
public class QueueBean implements QueueBeanLocal {
private static final Logger logger = LoggerFactory.getLogger(QueueBean.class);
/**
* Default constructor.
*/
public QueueBean() {
mapqueues = new HashMap<>();
logger.info("Initialized2 QueueBean, {}", mapqueues);
}
private final Map<Integer, MapQueue> mapqueues;
private int reservingSize = 2;
private class MapQueue {
// private final Set<MapReservationQueueEntry> reserving = new HashSet<>();
private final Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<EventUser, Boolean>());
private final LinkedBlockingQueue<EventUser> queue = new LinkedBlockingQueue<>();
private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>();
// public boolean enterReserving( EventUser user) {
// timeoutReserving();
//
// if (reserving.size() < 3 && !queue.isEmpty() && queue.get(0).equals(entry)) {
// entry = queue.get(0);
// entry.removeFromQueue();
// }
// }
private void timeoutEntries() {
// give 10 seconds mercy ( and give us some time to go through all entries)
Date now = new Date(System.currentTimeMillis() + 1000 * 15);
for (EventUser r : reserving) {
MapReservationQueueEntry entry = queEntries.get(r);
if (entry.getReservationTimeout() == null || now.after(entry.getReservationTimeout())) {
this.remove(entry.getUser());
}
}
// Set idle time to the past.
// Idle timeout after 60 seconds
Date idleTimeout = new Date(System.currentTimeMillis() - 1000 * 60);
for (EventUser q : queue) {
MapReservationQueueEntry entry = queEntries.get(q);
if (entry.getSeenTime() == null) {
entry.setSeenTime(new Date());
continue;
}
if (idleTimeout.after(entry.getSeenTime())) {
remove(entry.getUser());
}
}
}
public boolean isReserving(EventUser e) {
// Check queue size and add entry to queue
if (reserving.size() < reservingSize) {
synchronized (queue) {
if (reserving.size() < reservingSize) {
EventUser queEntry = queue.poll();
if (queEntry != null) {
reserving.add(queEntry);
}
}
}
}
MapReservationQueueEntry que = queEntries.get(e);
if (que != null) {
que.setSeenTime(new Date());
}
return reserving.contains(e);
}
public MapReservationQueueEntry remove(EventUser user)
{
MapReservationQueueEntry ret = null;
synchronized (queue) {
if (reserving.remove(user)) {
logger.info("Removed user {} from reserving queue", user);
}
// There should neve be more than one instance, but make sure
while (queue.remove(user)) {
logger.info("Removed user {} from queue");
}
ret = queEntries.remove(user);
}
return ret;
}
public MapReservationQueueEntry enter(EventUser user) {
MapReservationQueueEntry ret = null;
synchronized (queue) {
if (!reserving.contains(user) && !queue.contains(user)) {
ret = new MapReservationQueueEntry();
queEntries.put(user, ret);
boolean queStat = queue.offer(user);
logger.info("User {} not in queue, offer state {}", user, queStat);
} else {
ret = queEntries.get(user);
logger.info("User {} already in queue. Not entering again {}", user, ret);
}
}
return ret;
}
public Integer getPosition(EventUser user) {
Integer ret = null;
if (reserving.contains(user)) {
ret = 0;
logger.info("User in reserving queue {}", user);
} else if (queue.contains(user)) {
ret = 1;
for (EventUser eu : queue) {
if (eu.equals(user)) {
break;
}
++ret;
}
logger.info("User is in queue {}, position {}", user, ret);
} else {
logger.info("Not in queue, while checking position");
}
logger.info("Got position {} for user {}", ret, user);
return ret;
}
public boolean isInQueue(EventUser user) {
return reserving.contains(user) || queue.contains(user);
}
public MapReservationQueueEntry getEntry(EventUser user) {
return queEntries.get(user);
}
}
@EJB
private EventBeanLocal eventbean;
private AtomicLong nextReservingTimeoutCheck = new AtomicLong();
@EJB
private PlaceSlotFacade slotfacade;
@Lock(LockType.READ)
@Override
public boolean isReserving(EventMap map, EventUser user) {
// If queue is not enabled, user can always reserve
if (!isQueueEnabled())
return true;
if (map == null || user == null)
{
logger.warn("Can not check map {}, user {}", map, user);
}
boolean ret = getMapque(map).isReserving(user);
// Do some housekeeping, but only on each 120
long now = System.currentTimeMillis();
long nextTime = nextReservingTimeoutCheck.get();
// Update next checktime to 120 seconds in to the future, so we should have plenty of time
// to do the checks we need..
if (now > nextTime && nextReservingTimeoutCheck.compareAndSet(nextTime, now + 1000 * 120)) {
logger.info("Launcing reservingTimeout check ");
checkReservingTimeouts();
logger.info("Done launching reservingTimeoutCheck");
}
return ret;
}
@Asynchronous
private void checkReservingTimeouts() {
try {
final long oldTime = nextReservingTimeoutCheck.get();
for (MapQueue m : mapqueues.values()) {
m.timeoutEntries();
}
// DO housekeeping every 10 seconds.
nextReservingTimeoutCheck.compareAndSet(oldTime, System.currentTimeMillis() + 1000 * 10);
} catch (Throwable t) {
logger.warn("Exception while checking reservingTimeouts");
}
}
private MapQueue getMapque(EventMap map) {
if (map == null) {
return null;
}
MapQueue ret = mapqueues.get(map.getId());
if (ret == null) {
logger.info("getMapqueue, {}", mapqueues);
synchronized (mapqueues) {
ret = new MapQueue();
mapqueues.put(map.getId(), ret);
}
}
logger.info("returning queue {} for map {}", ret, map);
return ret;
}
@Lock(LockType.READ)
@Override
public Integer getQueuePosition(EventMap map, EventUser user)
{
return getMapque(map).getPosition(user);
}
@Lock(LockType.READ)
@Override
public boolean isQueueEnabled() {
boolean ret = false;
LanEventProperty mapque = eventbean.getProperty(LanEventPropertyKey.MAP_QUEUE);
if (mapque != null)
ret = mapque.isBooleanValue();
return ret;
}
@Lock(LockType.READ)
@Override
public MapReservationQueueEntry remove(EventMap map, EventUser user) {
MapQueue queue = getMapque(map);
return queue.remove(user);
}
@Override
@Lock(LockType.READ)
public MapReservationQueueEntry enterQueue(EventMap map, EventUser user) {
if (!isQueueEnabled()) {
return null;
}
MapQueue queue = getMapque(map);
MapReservationQueueEntry ret = null;
if (queue.isInQueue(user)) {
logger.info("User {} already in queue");
ret = queue.getEntry(user);
} else {
List<PlaceSlot> slots = slotfacade.findFreePlaceSlots(user, null);
logger.info("User {} not yet in queue. User has {} slots", user, slots.size());
if (!slots.isEmpty()) {
ret = queue.enter(user);
logger.info("Entered queue: {}", ret);
}
}
return ret;
}
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
package fi.codecrew.moya.facade; package fi.codecrew.moya.facade;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
...@@ -27,6 +28,7 @@ import javax.ejb.Stateless; ...@@ -27,6 +28,7 @@ import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path; import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -67,11 +69,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> { ...@@ -67,11 +69,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> {
CriteriaQuery<PlaceSlot> q = cb.createQuery(PlaceSlot.class); CriteriaQuery<PlaceSlot> q = cb.createQuery(PlaceSlot.class);
Root<PlaceSlot> root = q.from(PlaceSlot.class); Root<PlaceSlot> root = q.from(PlaceSlot.class);
Path<Bill> bill = root.get(PlaceSlot_.bill); Path<Bill> bill = root.get(PlaceSlot_.bill);
q.where(cb.equal(bill.get(Bill_.user), user), final List<Predicate> preds = new ArrayList<>();
cb.isNotNull(bill.get(Bill_.paidDate)), preds.add(cb.equal(bill.get(Bill_.user), user));
cb.isNull(root.get(PlaceSlot_.used)), preds.add(cb.isNotNull(bill.get(Bill_.paidDate)));
cb.equal(root.get(PlaceSlot_.product), product) preds.add(cb.isNull(root.get(PlaceSlot_.used)));
); if (product != null) {
preds.add(cb.equal(root.get(PlaceSlot_.product), product));
}
q.where(preds.toArray(new Predicate[preds.size()]));
return getEm().createQuery(q).getResultList(); return getEm().createQuery(q).getResultList();
} }
...@@ -102,18 +108,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> { ...@@ -102,18 +108,15 @@ public class PlaceSlotFacade extends IntegerPkGenericFacade<PlaceSlot> {
q.where(cb.equal(root.get(PlaceSlot_.product), prod), q.where(cb.equal(root.get(PlaceSlot_.product), prod),
cb.or(cb.isNull(billexp), cb.or(cb.isNull(billexp),
cb.greaterThan(billexp, Calendar.getInstance()) cb.greaterThan(billexp, Calendar.getInstance())
), ),
cb.isNull(root.get(PlaceSlot_.place)), cb.isNull(root.get(PlaceSlot_.place)),
cb.isNull(root.get(PlaceSlot_.used)) cb.isNull(root.get(PlaceSlot_.used))
); );
Long count = super.getSingleNullableResult(getEm().createQuery(q)); Long count = super.getSingleNullableResult(getEm().createQuery(q));
return count; return count;
} }
public Long totalSlotcount(Product prod) { public Long totalSlotcount(Product prod) {
CriteriaBuilder cb = getEm().getCriteriaBuilder(); CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Long> q = cb.createQuery(Long.class); CriteriaQuery<Long> q = cb.createQuery(Long.class);
......
...@@ -44,6 +44,7 @@ public enum LanEventPropertyKey { ...@@ -44,6 +44,7 @@ public enum LanEventPropertyKey {
TEMPLATE_PROPERTY5(Type.TEXT, null), TEMPLATE_PROPERTY5(Type.TEXT, null),
INVITE_ONLY_EVENT(Type.BOOL, null), INVITE_ONLY_EVENT(Type.BOOL, null),
USE_ETICKET(Type.BOOL, null), USE_ETICKET(Type.BOOL, null),
MAP_QUEUE(Type.BOOL, null),
; ;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
*/ */
package fi.codecrew.moya.model; package fi.codecrew.moya.model;
import java.awt.Color;
import java.util.Calendar; import java.util.Calendar;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
......
package fi.codecrew.moya.model.map;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.GenericEntity;
/**
*
*
*/
//mapQueGroup
//- queEnableTime
//- queDisableTime
//- maxSiultaneousPlaces
//- maxSimultaneoutUsers
//- minPlaces
//- maxPlaces
//- placecountWeight ( 1 = more places go first, 0 = fully random
//- queueTimeWeight ( 1 = fifo, 0 = fully random )
//@Entity
// @Table(name = "map_reservation_queue")
public class MapReservationQueue extends GenericEntity {
@ManyToOne
@JoinColumn(nullable = false)
private EventMap map;
private String name;
private String description;
@Temporal(TemporalType.TIMESTAMP)
private Date queueEnableTime;
@Temporal(TemporalType.TIMESTAMP)
private Date queueDisableTime;
// how many placeslots or users can be reserving places at the same time
private Integer simultaneousPlaceslots;
private Integer simultaneousUsers;
private Integer queMinPlaces;
private Integer queMaxPlaces;
// Bigger gets selected first if multiple queues apply to user
private Integer selectionPriority = 100;
// // 100 = more places go always first, 0 = fully random
// @Column(nullable = false, precision = 6, scale = 7)
// private Integer placeslotWeight;
//
// // ( 100 = fifo, 0 = fully random )
// private Integer queueTimeWeight;
// If there are multiple queues enabled, queueus with the same weight
// are evaluated against eachother. Queues with bigger priorities are always selected
// before queues with lower prorities
private Integer queueQuePriority = 10;
/**
*
*/
private static final long serialVersionUID = -6631083485543375943L;
public MapReservationQueue() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getQueueEnableTime() {
return queueEnableTime;
}
public void setQueueEnableTime(Date queueEnableTime) {
this.queueEnableTime = queueEnableTime;
}
public Date getQueueDisableTime() {
return queueDisableTime;
}
public void setQueueDisableTime(Date queueDisableTime) {
this.queueDisableTime = queueDisableTime;
}
public Integer getSimultaneousPlaceslots() {
return simultaneousPlaceslots;
}
public void setSimultaneousPlaceslots(Integer simultaneousPlaceslots) {
this.simultaneousPlaceslots = simultaneousPlaceslots;
}
public Integer getSimultaneousUsers() {
return simultaneousUsers;
}
public void setSimultaneousUsers(Integer simultaneousUsers) {
this.simultaneousUsers = simultaneousUsers;
}
public Integer getQueMinPlaces() {
return queMinPlaces;
}
public void setQueMinPlaces(Integer queMinPlaces) {
this.queMinPlaces = queMinPlaces;
}
public Integer getQueMaxPlaces() {
return queMaxPlaces;
}
public void setQueMaxPlaces(Integer queMaxPlaces) {
this.queMaxPlaces = queMaxPlaces;
}
public EventMap getMap() {
return map;
}
public void setMap(EventMap map) {
this.map = map;
}
public Integer getSelectionPriority() {
return selectionPriority;
}
public void setSelectionPriority(Integer selectionPriority) {
this.selectionPriority = selectionPriority;
}
public Integer getQueueQuePriority() {
return queueQuePriority;
}
public void setQueueQuePriority(Integer queueQuePriority) {
this.queueQuePriority = queueQuePriority;
}
}
package fi.codecrew.moya.model.map;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.GenericEntity;
//userque
//- user
//- enteredQueue
//- enteredSelection
// @Entity
// @Table(name = "map_reservation_queue_entry")
public class MapReservationQueueEntry extends GenericEntity {
/**
*
*/
private static final long serialVersionUID = -1529588850152306791L;
@Column()
@JoinColumn(nullable = false)
private MapReservationQueue queue;
@ManyToOne
private EventUser user;
@Temporal(TemporalType.TIMESTAMP)
private Date created;
@Temporal(TemporalType.TIMESTAMP)
private Date reservationTimeout;
@Transient
private Date seenTime;
// @OneToOne()
// @JoinColumn(nullable = true)
// private MapReservationQueueEntry previous;
//
// @OneToOne(mappedBy = "previous")
// private MapReservationQueueEntry next;
private static final Logger logger = LoggerFactory.getLogger(MapReservationQueueEntry.class);
// public void removeFromQueue() {
// if (previous != null) {
// if (!this.equals(previous.getNext())) {
// logger.warn("WTF!! Previous entrys next value does not match this! This '{}', Previous '{}', Next of previous '{}'", this, getPrevious(), getPrevious().getNext());
// }
// previous.setNext(next);
// previous = null;
// next = null;
// }
// }
//
// public void addToQueue(MapReservationQueueEntry previous) {
// if (previous != null) {
// next = previous.getNext();
// previous.setNext(this);
// if (next != null) {
// next.setPrevious(this);
// }
// }
// }
public MapReservationQueue getQueue() {
return queue;
}
public void setQueue(MapReservationQueue queue) {
this.queue = queue;
}
public EventUser getUser() {
return user;
}
public void setUser(EventUser user) {
this.user = user;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getReservationTimeout() {
return reservationTimeout;
}
public void setReservationTimeout(Date reservationTimeout) {
this.reservationTimeout = reservationTimeout;
}
public Date getSeenTime() {
return seenTime;
}
public void setSeenTime(Date seenTime) {
this.seenTime = seenTime;
}
}
...@@ -35,13 +35,26 @@ ...@@ -35,13 +35,26 @@
<h:outputScript target="head" library="seatjs" name="d3-tip.js" /> <h:outputScript target="head" library="seatjs" name="d3-tip.js" />
<h:outputScript target="head" library="seatjs" name="seatmap.js" /> <h:outputScript target="head" library="seatjs" name="seatmap.js" />
<h:outputStylesheet library="seatjs" name="placemap.css" /> <h:outputStylesheet library="seatjs" name="placemap.css" />
<div style="margin: 5px;"> <div style="margin: 5px;">
<h:form id="placeselectform"> <h:form id="placeselectform">
<h:commandButton rendered="#{ajaxMapView.canUserBuy()}" <p:commandButton rendered="#{ajaxMapView.canUserBuy()}"
value="#{i18n['mapView.buyPlaces']}" value="#{i18n['mapView.buyPlaces']}"
action="#{ajaxMapView.buySelectedPlaces()}" /> action="#{ajaxMapView.buySelectedPlaces()}" ajax="false" />
</h:form> </h:form>
</div> </div>
<h:form>
<p:commandButton value="#{i18n['mapView.enterQueue']}"
action="#{ajaxMapView.enterQueue()}" ajax="false" />
<p:commandButton value="#{i18n['mapView.check']}"
action="#{ajaxMapView.checkReserving()}" />
</h:form>
queueEntry #{ajaxMapView.queueEntry} <br />
QueuePosition: #{ajaxMapView.queuePosition} <br />
Available places to select: #{ajaxMapView.placesLeftToSelect} <br />
isReserving #{ajaxMapView.reserving} <br />
<svg id="seatmap" style="margin: auto; border: 1px solid black;" <svg id="seatmap" style="margin: auto; border: 1px solid black;"
width="#{ajaxMapView.map.width}px" width="#{ajaxMapView.map.width}px"
height="#{ajaxMapView.map.height}px" /> height="#{ajaxMapView.map.height}px" />
...@@ -90,7 +103,7 @@ ...@@ -90,7 +103,7 @@
<h:outputLabel value="#{i18n['placeSelect.placesleft']}:" /> <h:outputLabel value="#{i18n['placeSelect.placesleft']}:" />
<h:outputText value="#{ajaxMapView.placesLeftToSelect}" /> <h:outputText value="#{ajaxMapView.placesLeftToSelect}" />
</h:panelGrid> </h:panelGrid>
</h:panelGrid> </h:panelGrid>
......
...@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; ...@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PermissionBeanLocal; import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal; import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.QueueBeanLocal;
import fi.codecrew.moya.model.EventMap; import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Place; import fi.codecrew.moya.model.Place;
...@@ -47,6 +48,9 @@ public class PlacemapRestViewV1 { ...@@ -47,6 +48,9 @@ public class PlacemapRestViewV1 {
@Inject @Inject
private UserView userView; private UserView userView;
@EJB
private QueueBeanLocal quebean;
// @GET // @GET
// @Path("/maps") // @Path("/maps")
// public PlacemapMapRootPojo getMaps() // public PlacemapMapRootPojo getMaps()
...@@ -116,6 +120,13 @@ public class PlacemapRestViewV1 { ...@@ -116,6 +120,13 @@ public class PlacemapRestViewV1 {
} }
Place p = placebean.find(placeId); Place p = placebean.find(placeId);
EventMap map = p.getMap();
if (!quebean.isReserving(map, user))
{
logger.warn("User is not in reservation order ");
return Response.status(Response.Status.FORBIDDEN).build();
}
boolean success = false; boolean success = false;
if (p.isReservedFor(user)) { if (p.isReservedFor(user)) {
success = placebean.releasePlace(p); success = placebean.releasePlace(p);
......
...@@ -5,6 +5,7 @@ import java.util.Map; ...@@ -5,6 +5,7 @@ import java.util.Map;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped; import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext; import javax.faces.context.FacesContext;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
...@@ -15,25 +16,27 @@ import org.slf4j.LoggerFactory; ...@@ -15,25 +16,27 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.EventBeanLocal; import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal; import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal; import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.beans.QueueBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission; import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.exceptions.BortalCatchableException; import fi.codecrew.moya.exceptions.BortalCatchableException;
import fi.codecrew.moya.model.EventMap; import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEvent; import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Place; import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.map.MapReservationQueueEntry;
import fi.codecrew.moya.web.cdiview.GenericCDIView; import fi.codecrew.moya.web.cdiview.GenericCDIView;
import fi.codecrew.moya.web.cdiview.user.UserView; import fi.codecrew.moya.web.cdiview.user.UserView;
@Named @Named
@ConversationScoped @RequestScoped
public class AjaxMapView extends GenericCDIView { public class AjaxMapView extends GenericCDIView {
/** /**
* *
*/ */
private static final long serialVersionUID = 8203589456357519480L; private static final long serialVersionUID = 8203589456357519480L;
@Inject // @Inject
private PlaceView placeview; // private PlaceView placeview;
private static final Logger logger = LoggerFactory.getLogger(AjaxMapView.class);; private static final Logger logger = LoggerFactory.getLogger(AjaxMapView.class);;
private String testVal = "Testval1"; private String testVal = "Testval1";
...@@ -53,6 +56,9 @@ public class AjaxMapView extends GenericCDIView { ...@@ -53,6 +56,9 @@ public class AjaxMapView extends GenericCDIView {
@Inject @Inject
private UserView userview; private UserView userview;
@EJB
private QueueBeanLocal quebean;
public void initReserveMap() { public void initReserveMap() {
initMap(); initMap();
map = placebean.findMap(mapId); map = placebean.findMap(mapId);
...@@ -62,6 +68,26 @@ public class AjaxMapView extends GenericCDIView { ...@@ -62,6 +68,26 @@ public class AjaxMapView extends GenericCDIView {
initMap(); initMap();
} }
private Boolean queEnabled = null;
private MapReservationQueueEntry queueEntry;
public boolean isQueueEnabled() {
if (queEnabled == null)
queEnabled = quebean.isQueueEnabled();
return queEnabled;
}
public String enterQueue()
{
logger.info("Entering queue");
if (isQueueEnabled())
queueEntry = quebean.enterQueue(initMap(), permbean.getCurrentUser());
else {
logger.warn("QueueNot enabled. Not entering queue");
}
return null;
}
private EventMap initMap() { private EventMap initMap() {
if (map == null && mapId != null) { if (map == null && mapId != null) {
map = placebean.findMap(mapId); map = placebean.findMap(mapId);
...@@ -78,31 +104,50 @@ public class AjaxMapView extends GenericCDIView { ...@@ -78,31 +104,50 @@ public class AjaxMapView extends GenericCDIView {
} }
} }
} }
return map; return map;
} }
public Integer getQueuePosition() {
return quebean.getQueuePosition(initMap(), permbean.getCurrentUser());
}
public Long getPlacesLeftToSelect() { public Long getPlacesLeftToSelect() {
Long ret = placebean.selectablePlaceCount(initMap()); Long ret = placebean.selectablePlaceCount(initMap());
logger.debug("Got {} places left for map {}", ret, initMap()); logger.debug("Got {} places left for map {}", ret, initMap());
return ret; return ret;
} }
public Long getAvailablePlaces() { public Long getAvailablePlaces() {
Long ret = placebean.availablePlaceCount(initMap()); Long ret = placebean.availablePlaceCount(initMap());
// logger.debug("Got {} availbale places for map {}", ret, initMap()); // logger.debug("Got {} availbale places for map {}", ret, initMap());
return ret; return ret;
} }
public void checkReserving() {
}
public boolean isReserving()
{
return quebean.isReserving(initMap(), permbean.getCurrentUser());
}
public boolean canUserBuy() { public boolean canUserBuy() {
return permbean.hasPermission(MapPermission.BUY_PLACES); return permbean.hasPermission(MapPermission.BUY_PLACES) &&
(permbean.hasPermission(MapPermission.MANAGE_OTHERS) ||
quebean.isReserving(initMap(), permbean.getCurrentUser())
);
} }
public String buySelectedPlaces() { public String buySelectedPlaces() {
try { try {
EventUser user = userview.getSelectedUser(); EventUser user = userview.getSelectedUser();
placebean.buySelectedPlaces(user); placebean.buySelectedPlaces(user);
quebean.remove(initMap(), user);
return "/place/myGroups"; return "/place/myGroups";
} catch (BortalCatchableException e) { } catch (BortalCatchableException e) {
addFaceMessage("mapView.errorWhileBuyingPlaces"); addFaceMessage("mapView.errorWhileBuyingPlaces");
...@@ -163,4 +208,12 @@ public class AjaxMapView extends GenericCDIView { ...@@ -163,4 +208,12 @@ public class AjaxMapView extends GenericCDIView {
public void setContext(FacesContext context) { public void setContext(FacesContext context) {
this.context = context; this.context = context;
} }
public MapReservationQueueEntry getQueueEntry() {
return queueEntry;
}
public void setQueueEntry(MapReservationQueueEntry queueEntry) {
this.queueEntry = queueEntry;
}
} }
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!