package org.jboss.seam.example.seambay;
import static org.jboss.seam.ScopeType.CONVERSATION;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.Conversation;
@Scope(CONVERSATION)
@Name("bidAction")
public class BidAction
{
@In EntityManager entityManager;
private Bid bid;
@In(required = false) @Out(required = false)
private Auction auction;
@In(required = false)
private Account authenticatedAccount;
private String outcome;
@Begin(join = true)
public void placeBid()
{
if (auction.getStatus() != Auction.STATUS_LIVE ||
auction.getEndDate().getTime() < System.currentTimeMillis())
{
outcome = "ended";
}
else
{
bid = new Bid();
bid.setAuction(auction);
updateBid();
}
}
public void updateBid()
{
String amt = Contexts.getEventContext().isSet("bidAmount") ?
Contexts.getEventContext().get("bidAmount").toString() : null;
if (amt != null)
{
double amount = Double.parseDouble(amt.toString());
if (amt != null && amount >= bid.getAuction().getRequiredBid())
{
bid.setMaxAmount(amount);
outcome = "confirm";
}
else
{
outcome = "invalid";
}
}
else
{
outcome = "required";
}
}
@SuppressWarnings("unchecked")
public String confirmBid()
{
// We set the user here because the user may not be authenticated when placeBid() is called.
bid.setAccount(authenticatedAccount);
bid.setBidDate(new Date());
// This is where the tricky bidding logic happens
if (!entityManager.contains(bid.getAuction()))
{
bid.setAuction(entityManager.find(Auction.class, bid.getAuction().getAuctionId()));
}
entityManager.refresh(bid.getAuction());
if (bid.getAuction().getStatus() != Auction.STATUS_LIVE)
{
outcome = "ended";
return outcome;
}
else if (bid.getAuction().getEndDate().getTime() < bid.getBidDate().getTime())
{
bid.getAuction().setStatus(Auction.STATUS_COMPLETED);
outcome = "ended";
return outcome;
}
List<Bid> bids = entityManager.createQuery(
"from Bid b where b.auction = :auction")
.setParameter("auction", bid.getAuction())
.getResultList();
Bid highBid = null;
for (Bid b : bids)
{
if (highBid == null)
{
highBid = b;
}
else if (b.getMaxAmount() > highBid.getMaxAmount())
{
highBid.setActualAmount(highBid.getMaxAmount());
b.setActualAmount(Auction.getRequiredBid(highBid.getMaxAmount()));
highBid = b;
}
else if (b.getMaxAmount() == highBid.getMaxAmount() &&
b.getBidDate().getTime() < highBid.getBidDate().getTime())
{
highBid.setActualAmount(highBid.getMaxAmount());
b.setActualAmount(highBid.getMaxAmount());
highBid = b;
}
}
if (highBid == null)
{
// There are no bids so far...
bid.setActualAmount(bid.getAuction().getRequiredBid());
bid.getAuction().setHighBid(bid);
outcome = "success";
}
else if (bid.getMaxAmount() > highBid.getMaxAmount())
{
// If this bid is higher than the previous maximum bid, and is from
// a different bidder, set the actual amount to the next required bid
// amount for the auction
if (!bid.getAccount().equals(highBid.getAccount()))
{
bid.setActualAmount(Auction.getRequiredBid(highBid.getMaxAmount()));
}
else
{
// Otherwise don't change the amount from the bidder's last bid
bid.setActualAmount(highBid.getActualAmount());
}
bid.getAuction().setHighBid(bid);
outcome = "success";
}
else
{
if (!bid.getAccount().equals(highBid.getAccount()))
{
// Set this bid, and the highest bid's, actual bid amount to this
// bid's maximum amount
highBid.setActualAmount(bid.getMaxAmount());
bid.setActualAmount(bid.getMaxAmount());
outcome = "outbid";
}
else
{
outcome = "invalid";
}
}
if ("success".equals(outcome) || "outbid".equals(outcome))
{
bid.getAuction().setBids(bid.getAuction().getBids() + 1);
entityManager.persist(bid);
if ("success".equals(outcome))
{
Conversation.instance().end();
}
else
{
Bid newBid = new Bid();
newBid.setAuction(bid.getAuction());
newBid.setMaxAmount(bid.getMaxAmount());
bid = newBid;
}
}
return outcome;
}
public String getOutcome()
{
return outcome;
}
public Bid getBid()
{
return bid;
}
public Auction getAuction()
{
return auction;
}
}