ReaderBean.java 8.78 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.beans;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.ejb.Stateless;

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

import fi.codecrew.moya.facade.CardCodeFacade;
import fi.codecrew.moya.facade.PrintedCardFacade;
import fi.codecrew.moya.facade.ReaderEventFacade;
import fi.codecrew.moya.facade.ReaderFacade;
import fi.codecrew.moya.model.AccountEvent;
import fi.codecrew.moya.model.CardCode;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.PrintedCard;
import fi.codecrew.moya.model.Product;
import fi.codecrew.moya.model.Reader;
import fi.codecrew.moya.model.ReaderEvent;
import fi.codecrew.moya.model.ReaderEventType;
import fi.codecrew.moya.model.ReaderType;
import fi.codecrew.moya.model.User;

/**
 * Session Bean implementation class ReaderBean
 */
@Stateless
public class ReaderBean implements ReaderBeanLocal {

	@EJB
	private ReaderFacade readerfacade;

	@EJB
	private PrintedCardFacade cardfacade;

	@EJB
	private CardTemplateBeanLocal cardtemplatebean;
	@EJB
	private ReaderEventFacade readerEventFacade;
	@EJB
	private EventBeanLocal eventbean;
	@EJB
	private UserBeanLocal userbean;
	@EJB
	private CardTemplateBean cardTemplateBean;
	@EJB
	private ProductPBean productPBean;

	@EJB
	private CardCodeFacade cardCodeFacade;

	@EJB
	private BarcodeBeanLocal barcodeBean;

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

	@Override
	public ReaderEvent checkCode(String code) {
		return checkCode(ReaderType.BARCODE.toString() + ":handheld_reader_via_browser", code);
	}

	@Override
	public ReaderEvent checkCode(String readerIdent, String code) {
		Reader reader = readerfacade.findOrCreateByIdent(readerIdent);
		return checkCode(reader, code);
	}

	@Override
	/** 
	 * check reader code, and add it to the database
	 */
	public ReaderEvent checkCode(Reader reader, String code) {

		if (reader == null || code == null || code.isEmpty()) {
			return null;
		}

		logger.info("got code from reader {}", code);

		code = code.replace("\"\b", "");

		/**
		 * Some of rfid-readers adds zeros to start, some to end
		 * 
		 * Also, under  16 char -rdid (the smaller one) should be 16 character
		 * long, with zeros on beginning.
		 */
		if (ReaderType.RFID.equals(reader.getType())) {

			if (Pattern.matches("^.*000000$", code))
			{
				code = code.replace("000000", "");
			}
			StringBuilder sb = new StringBuilder(code);
			while (sb.length() < 16)
			{
				sb.insert(0, "0");
			}
			code = sb.toString();
		}

		ReaderEvent event = new ReaderEvent(new Date(), reader, code);

		// first, check if dublicate, there is 30s timeout for dublicates,
		// afther that it's ok to create dublicate
		// that's bcause accident dublicates are bad, but otherwise it's
		// probably bcause user want's to read it again
		List<ReaderEvent> lastevents = readerEventFacade.findLastEvents(reader, 1);

		if (!lastevents.isEmpty() && !reader.isAutoproduct())
		{
			ReaderEvent lastevent = lastevents.get(0);

			if (lastevent.getValue().equals(event.getValue()) && (lastevent.getUpdatetime().getTime() + 60000l) > event.getTime().getTime()) {

				//lastevent = readerEventFacade.reload(lastevent);
				//lastevent = readerEventFacade.merge(lastevent);

				return lastevent; // todo: update lastevent bfore return
			}
		}

		// find stuff with barcode and set type
		// IF we find 2 stuff with same barcode, it's just bad luck and things
		// may be little random.
		EventUser user = barcodeBean.getUser(code);

		if (user != null) {
			event.setType(ReaderEventType.USER);
			event.setUser(user);
		}

		PrintedCard card = barcodeBean.getPrintedCard(code);

		if (card != null) {
			event.setType(ReaderEventType.CARD);
			event.setPrintedCard(card);

			if (card.getUser() != null) {
				event.setUser(card.getUser());
			}
		}

		Product product = barcodeBean.getProduct(code);

		if (product != null) {
			event.setType(ReaderEventType.PRODUCT);
			event.setProduct(product);
		}

		Place place = barcodeBean.getPlaceFromBarcode(code);

		if (place != null) {
			event.setType(ReaderEventType.PLACE);
			event.setPlace(place);
		}

		event.setUpdatetime(new Date());

		// reader is in autoproduct-mode, create dat product
		if (reader.isAutoproduct()) {
			EventUser eu = userbean.getEventUser(card.getUser().getUser(), false);
			if (eu != null) {
				AccountEvent createAc = productPBean.createAccountEvent(reader.getAutomaticProduct(), reader.getAutomaticProductCount(),  eu, new Date(), "Created automatically");
				readerfacade.flush();
				logger.info("Creating new accountevent from autoproduct {}", createAc);
				event.setNotes("Created automatic account event from reader. " + createAc);
			}
		}

		readerEventFacade.create(event);

		return event;

	}

	@Override
	public ReaderEvent assocCodeToCard(ReaderEvent readerEvent, PrintedCard card) {

		// you can select between this and flushCache.
		card = cardfacade.reload(card);

		CardCode code = new CardCode(card, readerEvent.getReader().getType(), readerEvent.getValue(), eventbean.getCurrentEvent());

		cardCodeFacade.create(code);

		card.getCardCodes().add(code);
		cardCodeFacade.flush();

		return checkCode(readerEvent.getReader(), readerEvent.getValue());
	}

	@Override
	public List<Reader> getReaders() {
		return readerfacade.findAllForEvent();
	}

	@Override
	public List<ReaderEvent> getReaderEvents(Integer readerId) {
		return getReaderEvents(readerId, 20);
	}

	@Override
	public List<ReaderEvent> getReaderEvents(Integer readerId, Integer count) {

		logger.info("Getting events for reader {}", readerId);
		Reader reader = readerfacade.find(readerId);
		return readerEventFacade.findLastEvents(reader, count);
	}

	@Override
	public ReaderEvent getLastReaderEvent(Integer readerId) {
		Reader reader = readerfacade.find(readerId);

		List<ReaderEvent> list = readerEventFacade.findLastEvents(reader, 1);

		if (list.size() > 0)
			return list.get(0);

		return null;
	}

	@Override
	public ReaderEvent getEvent(Integer eventid) {
		ReaderEvent ret = readerEventFacade.find(eventid);
		if (!ret.getReader().getEvent().equals(eventbean.getCurrentEvent()))
		{
			ret = null;
		}
		return ret;
	}

	@Override
	public User findTagFromAnyEvent(String value) {
		PrintedCard card = cardfacade.findLatestByCodeFromAny(value);
		User ret = null;
		if (card != null && card.getUser() != null) {
			ret = card.getUser().getUser();
		}

		return ret;
	}

	// ok, let's comment this out, so I can see where this is used
	/*
	 * @Override public ReaderEvent createCard(ReaderEvent event, EventUser
	 * user) { ReaderEvent ret = null;
	 * logger.info("Trying to create card for event {} with printed card {}",
	 * event, event.getPrintedCard());
	 * 
	 * if (event.getPrintedCard() == null) { CardTemplate ct =
	 * cardTemplateBean.getUsersCardtype(user); logger.info("Card template {}",
	 * ct); if (ct == null) { return null; } PrintedCard card = new
	 * PrintedCard(user, ct, null, true); card.setRfidUid(event.getValue());
	 * cardfacade.create(card);
	 * 
	 * ret = new ReaderEvent(Calendar.getInstance(), card, event.getReader());
	 * card.getReaderEvents().add(event);
	 * ret.setNotes("User associated to a card");
	 * 
	 * } return ret; }
	 */

	@Override
	public Reader getReader(Integer readerid) {
		return readerfacade.findReader(readerid);
	}

	@Override
	public Reader saveReader(Reader reader) {
		if (!eventbean.getCurrentEvent().equals(reader.getEvent())) {
			throw new EJBAccessException("Trying to save reader from wrong event");
		}
		return readerfacade.merge(reader);
	}

	@Override
	public void createReader(Reader reader) {
		reader.setEvent(eventbean.getCurrentEvent());
		readerfacade.create(reader);

	}

	@Override
	public List<ReaderEvent> getLastReaderEvents() {
		List<ReaderEvent> ret = new ArrayList<>();
		for (Reader r : readerfacade.findAllForEvent())
		{
			ret.addAll(readerEventFacade.findLastEvents(r, 1));
		}
		return ret;
	}

	@Override
	public List<ReaderEvent> getReaderEventsAfterEvent(Integer readerId, Integer eventId) {
		Reader reader = getReader(readerId);
		return readerEventFacade.findEventsAfterEvent(reader, eventId);
	}
}