/**
* A request from a Brewer to the warehouse.
*
* CS 537, Spring 2007, Project 3.
*
* A Request keeps track of the amounts requested and allocated thus far, and
* serves as a waiting place for the ordering thread to wait for completion.
*/
public class Request {
/** Source version number. */
private static final int VERSION = 3;
/** Source of sequence numbers. */
private static int nextSeq = 0;
/** The original amount requested. */
private Order requested;
/** The requesting customer's id (for debugging output). */
private int id;
/** The sequence number of this request in the order received. */
public final int seq;
/** The amount allocated thus far. */
private Order alloc;
/** Flag to indicate this Request is satisfied. */
private boolean completed = false;
/** Creates a new Request.
* Note: This method is not thread-safe, so it should be only called from
* a synchronized method that prevents two concurrent invocations of
* "new Request(...)".
* @param id the requesting customer's id (for debugging output).
* @param request the amount of each commodity needed.
*/
public Request(int id, Order request) {
this.id = id;
this.requested = request.copy();
this.seq = ++nextSeq;
alloc = new Order();
} // Request(Order)
/** Check whether the unfilled portion of this request is less than or
* equal to supply (in all grains).
* @param supply the amount to compare to.
* @return true if the request can be completely satisfied by supply.
*/
public synchronized boolean lessOrEqual(Order supply) {
for (Grain g : Grain.values()) {
if (requested.get(g) - alloc.get(g) > supply.get(g)) {
return false;
}
}
return true;
} // lessOrEqual(Order)
/** Allocate some grain to this Request from supply.
* The amount of each grain given is the minimum of the amount in supply
* and the amount needed to complete the order. However, if limit is
* postive, no more than 'limit' bushels of any grain will be given.
* @param supply the source of grain.
* @param limit if greater than zero, do not give more than this many
* bushels of any one grain.
* @return the total number of bushels of grain given.
*/
public synchronized int give(Order supply, int limit) {
int result = 0;
for (Grain g : Grain.values()) {
int amt = requested.get(g) - alloc.get(g);
if (amt > supply.get(g)) {
amt = supply.get(g);
}
if (limit > 0 && amt > limit) {
amt = limit;
}
alloc.change(g, amt);
supply.change(g, -amt);
result += amt;
}
return result;
} // give(Order,int)
/** Check whether this order is satified.
* @return true if the amount allocated matches the amount requested, for
* all resources.
*/
public synchronized boolean satisfied() {
for (Grain g : Grain.values()) {
if (alloc.get(g) != requested.get(g)) {
return false;
}
}
return true;
} // satisfied()
/** Return the total amount requested.
* @return the sum of the numbers of bushels of all grains.
*/
public synchronized int size() {
int sum = 0;
for (Grain g : Grain.values()) {
sum += requested.get(g);
}
return sum;
} // size()
/** Return the remaining amount requested.
* @return the sum of request - alloc over all grains.
*/
public synchronized int remaining() {
int sum = 0;
for (Grain g : Grain.values()) {
sum += requested.get(g) - alloc.get(g);
}
return sum;
} // remaining()
/** Signal completion.
* The customer who placed this order is allowed to return.
*/
public synchronized void complete() {
completed = true;
notify();
} // complete()
/** Await fulfillment of this order.
* @throws InterruptedException if the current thread is interrupted while
* waiting for the request to be filled.
*/
public synchronized void await() throws InterruptedException {
while (!completed) {
wait();
}
} // await()
/** Gets the current allocation to this request.
*
* @return the current amount allocated
*/
public synchronized Order getAlloc() {
return alloc;
} // getAlloc()
/** Turn a Request into a printable string.
* @return a printable version of this request.
*/
public String toString() {
StringBuffer sb = new StringBuffer(seq + ":" + id);
char sep = '[';
for (Grain g : Grain.values()) {
sb.append(String.format(
"%c%d/%d %s", sep, alloc.get(g), requested.get(g), g));
sep = ',';
}
sb.append(']');
return sb.toString();
} // toString()
} // Request