package com.workshare.msnos.core.receipts; import java.util.UUID; import java.util.concurrent.TimeUnit; import com.workshare.msnos.core.Gateway; import com.workshare.msnos.core.Message; import com.workshare.msnos.core.Message.Status; import com.workshare.msnos.core.protocols.ip.NullGateway; import com.workshare.msnos.core.Receipt; import com.workshare.msnos.soup.time.SystemTime; public class SingleReceipt implements Receipt { private final UUID messageUuid; private String gate; private Status status; public SingleReceipt(Gateway gateway, Status status, Message message) { this(gateway.name(), status, message); } protected SingleReceipt(String gatewayName, Status status, Message message) { this.status = status; this.messageUuid = message.getUuid(); this.gate = gatewayName; } @Override public UUID getMessageUuid() { return messageUuid; } @Override public synchronized Status getStatus() { return status; } public synchronized void update(Receipt other) { if (!messageUuid.equals(other.getMessageUuid())) throw new IllegalArgumentException("You cannot update a receipt related to another message!"); this.gate = other.getGate(); this.status = other.getStatus(); notifyAll(); } @Override public synchronized boolean waitForDelivery(long amount, TimeUnit unit) throws InterruptedException { switch (status) { case DELIVERED: return true; case FAILED: return false; default: doWaitForDelivery(amount, unit); return status == Status.DELIVERED; } } private void doWaitForDelivery(long amount, TimeUnit unit) throws InterruptedException { final long start = SystemTime.asMillis(); final long total = unit.toMillis(amount); while(elapsedFrom(start) < total) { this.wait(total); if (status == Status.DELIVERED || status == Status.FAILED) return; } } private final long elapsedFrom(long start) { return SystemTime.asMillis() - start; } @Override public String getGate() { return gate; } @Override public String toString() { return getStatus()+":"+messageUuid; } public static SingleReceipt failure(Message message) { return new SingleReceipt(NullGateway.NAME, Status.FAILED, message); } public static SingleReceipt unknown(Message message) { return new SingleReceipt(NullGateway.NAME, Status.UNKNOWN, message); } }