基於JADE的一個多 Agent 應用系統(“圖書交易”系統)
阿新 • • 發佈:2018-12-25
和處理賣方 Agent訊息佇列中來至買方的攜帶購買請求資訊(通訊原語為ACCEPT_PROPOSAL)的訊息。該行為在收到該訊息後,從本地圖書雜湊表中查詢是否有購買請求訊息中指定的圖書,若有則刪除該圖書,回覆買方agent一條通訊原語為INFORM的購買成功確認訊息,並終止該書對應的價格管理行為PriceManager;若沒有則回覆買方agent一條通訊原語為FAILURE的購買失敗訊息。
附原始碼:
BookBuyerAgent.java
BookSellerAgent.javapackage com.leejay.booktrading.buyer; import jade.core.AID; import jade.core.Agent; import jade.core.behaviours.Behaviour; import jade.core.behaviours.TickerBehaviour; import jade.domain.DFService; import jade.domain.FIPAException; import jade.domain.FIPAAgentManagement.DFAgentDescription; import jade.domain.FIPAAgentManagement.ServiceDescription; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import java.util.Date; import java.util.Vector; public class BookBuyerAgent extends Agent { // The list of known seller agents private Vector sellerAgents = new Vector(); // The GUI to interact with the user private BookBuyerGui myGui; /** * Agent initializations **/ protected void setup() { // Printout a welcome message System.out.println("Buyer-agent " + getAID().getName() + " is ready."); // Get names of seller agents as arguments /* * Object[] args = getArguments(); if (args != null && args.length > 0) * { for (int i = 0; i < args.length; ++i) { AID seller = new * AID((String) args[i], AID.ISLOCALNAME); * sellerAgents.addElement(seller); } } */ // Show the GUI to interact with the user myGui = new BookBuyerGuiImpl(); myGui.setAgent(this); myGui.show(); /** * This piece of code, to search services with the DF, is explained in * the book in section 4.4.3 **/ // Update the list of seller agents every 6s addBehaviour(new SearchSeller(this, 6000)); } /** * Agent clean-up **/ protected void takeDown() { // Dispose the GUI if it is there if (myGui != null) { myGui.dispose(); } // Printout a dismissal message System.out.println("Buyer-agent " + getAID().getName() + "terminated."); } /** * This method is called by the GUI when the user inserts a new book to buy * * @param title * The title of the book to buy * @param maxPrice * The maximum acceptable price to buy the book * @param deadline * The deadline by which to buy the book **/ public void purchase(String title, int maxPrice, Date deadline) { // the following line is in the book at page 62 addBehaviour(new PurchaseManager(this, title, maxPrice, deadline)); } /** * This method is called by the GUI. At the moment it is not implemented. **/ /* * public void setCreditCard(String creditCarNumber) { } */ /** * Inner class SearchSeller. This is the behaviour used by Book-buyer agents * to Update the list of seller agents every 6s * */ private class SearchSeller extends TickerBehaviour { public SearchSeller(Agent a, long time) { super(a, time); } @Override protected void onTick() { DFAgentDescription template = new DFAgentDescription(); ServiceDescription templateSd = new ServiceDescription(); templateSd.setType("book-trade"); template.addServices(templateSd); try { DFAgentDescription[] result = DFService.search(getAgent(), template); //update sellerAgents sellerAgents.clear(); for (int i = 0; i < result.length; i++) { sellerAgents.add(result[i].getName()); } } catch (FIPAException fe) { fe.printStackTrace(); } } } /** * Section 4.2.4, Page 62 **/ private class PurchaseManager extends TickerBehaviour { private String title; private int maxPrice, startPrice =0; private long deadline, initTime, deltaT; private PurchaseManager(Agent a, String t, int mp, Date d) { super(a, 6000); // tick every minute title = t; maxPrice = mp; deadline = d.getTime(); initTime = System.currentTimeMillis(); deltaT = deadline - initTime; } public void onTick() { long currentTime = System.currentTimeMillis(); if (currentTime > deadline) { // Deadline expired myGui.notifyUser("Cannot buy book " + title); stop(); } else { // Compute the currently acceptable price and start a // negotiation long elapsedTime = currentTime - initTime; int acceptablePrice = (int) Math.round(1.0 * maxPrice * (1.0 * elapsedTime / deltaT)); // System.out.println("elapsedTime"+elapsedTime+"deltaT"+deltaT+"acceptablePrice"+acceptablePrice+"maxPrice="+maxPrice); myAgent.addBehaviour(new BookNegotiator(title, acceptablePrice, this)); } } } /** * Section 4.3.5 of the book, page 69 Inner class BookNegotiator. This is * the behaviour used by Book-buyer agents to actually negotiate with seller * agents the purchase of a book. **/ private class BookNegotiator extends Behaviour { private String title; private int maxPrice; //maxmimum accepted price private PurchaseManager manager; private AID bestSeller; // The seller agent who provides the best offer private int bestPrice; // The best offered price private int repliesCnt = 0; // The counter of replies from seller agents private MessageTemplate mt; // The template to receive replies private int step = 0; public BookNegotiator(String t, int p, PurchaseManager m) { super(null); title = t; maxPrice = p; manager = m; } public void action() { switch (step) { case 0: // Send the cfp to all sellers ACLMessage cfp = new ACLMessage(ACLMessage.CFP); for (int i = 0; i < sellerAgents.size(); ++i) { cfp.addReceiver((AID) sellerAgents.elementAt(i)); } cfp.setContent(title); cfp.setConversationId("book-trade"); cfp.setReplyWith("cfp" + System.currentTimeMillis()); // Unique // value myAgent.send(cfp); myGui.notifyUser("Sent Call for Proposal"); // Prepare the template to get proposals mt = MessageTemplate.and( MessageTemplate.MatchConversationId("book-trade"), MessageTemplate.MatchInReplyTo(cfp.getReplyWith())); step = 1; break; case 1: // Receive all proposals/refusals from seller agents ACLMessage reply = myAgent.receive(mt); if (reply != null) { // Reply received if (reply.getPerformative() == ACLMessage.PROPOSE) { // This is an offer int price = Integer.parseInt(reply.getContent()); myGui.notifyUser("Received Proposal at " + price + " when maximum acceptable price was " + maxPrice); if (bestSeller == null || price < bestPrice) { // This is the best offer at present bestPrice = price; bestSeller = reply.getSender(); } } repliesCnt++; if (repliesCnt >= sellerAgents.size()) { // We received all replies step = 2; } } else { block(); } break; case 2: if (bestSeller != null && bestPrice <= maxPrice) { // Send the purchase order to the seller that provided the // best offer ACLMessage order = new ACLMessage( ACLMessage.ACCEPT_PROPOSAL); order.addReceiver(bestSeller); order.setContent(title); order.setConversationId("Book-selling"); order.setReplyWith("order" + System.currentTimeMillis()); myAgent.send(order); myGui.notifyUser("sent Accept Proposal"); // Prepare the template to get the purchase order reply mt = MessageTemplate.and(MessageTemplate .MatchConversationId("book-trade"), MessageTemplate .MatchInReplyTo(order.getReplyWith())); step = 3; } else { // If we received no acceptable proposals, terminate step = 4; } break; case 3: // Receive the purchase order reply reply = myAgent.receive(mt); if (reply != null) { // Purchase order reply received if (reply.getPerformative() == ACLMessage.INFORM) { // Purchase successful. We can terminate myGui.notifyUser("Book " + title + " successfully purchased. Price = " + bestPrice); manager.stop(); } step = 4; } else { block(); } break; } // end of switch } public boolean done() { return step == 4; } } // End of inner class BookNegotiator }
BookBuyerGui.javapackage com.leejay.booktrading.seller; import jade.core.Agent; import jade.core.behaviours.CyclicBehaviour; import jade.core.behaviours.TickerBehaviour; import jade.domain.DFService; import jade.domain.FIPAException; import jade.domain.FIPAAgentManagement.DFAgentDescription; import jade.domain.FIPAAgentManagement.ServiceDescription; import jade.lang.acl.ACLMessage; import jade.lang.acl.MessageTemplate; import java.io.File; import java.io.FileInputStream; import java.util.Date; import java.util.HashMap; import java.util.Map; public class BookSellerAgent extends Agent { // The catalogue of books available for sale private Map catalogue = new HashMap(); // The GUI to interact with the user private BookSellerGui myGui; public static final String SERVICE_NAME = "sell_service"; /** * Agent initializations **/ protected void setup() { // Printout a welcome message System.out.println("Seller-agent " + getAID().getName() + " is ready."); // Create and show the GUI myGui = new BookSellerGuiImpl(); myGui.setAgent(this); myGui.show(); // Add the behaviour serving calls for price from buyer agents addBehaviour(new CallForOfferServer()); // Add the behaviour serving purchase requests from buyer agents addBehaviour(new PurchaseOrderServer()); /** * This piece of code, to register services with the DF, is explained in * the book in section 4.4.2.1 **/ // Register the book-selling service in the yellow pages registService(); } /** * Register the book-selling service in the yellow pages */ private void registService() { DFAgentDescription dfd = new DFAgentDescription(); dfd.setName(getAID()); ServiceDescription sd = new ServiceDescription(); sd.setName(SERVICE_NAME); sd.setType("Book-selling"); dfd.addServices(sd); try { DFService.register(this, dfd); } catch (FIPAException fe) { fe.printStackTrace(); } } /** * Agent clean-up **/ protected void takeDown() { // Dispose the GUI if it is there if (myGui != null) { myGui.dispose(); } // Printout a dismissal message System.out.println("Seller-agent " + getAID().getName() + "terminating."); /** * This piece of code, to deregister with the DF, is explained in the * book in section 4.4.2.1, page 73 **/ // Deregister from the yellow pages try { DFService.deregister(this); } catch (FIPAException e) { e.printStackTrace(); } } /** * This method is called by the GUI when the user inserts a new book for * sale * * @param title * The title of the book for sale * @param initialPrice * The initial price * @param minPrice * The minimum price * @param deadline * The deadline by which to sell the book **/ public void putForSale(String title, int initPrice, int minPrice, Date deadline) { addBehaviour(new PriceManager(this, title, initPrice, minPrice, deadline)); } private class PriceManager extends TickerBehaviour { private String title; private int minPrice, currentPrice, initPrice, deltaP; private long initTime, deadline, deltaT; private PriceManager(Agent a, String t, int ip, int mp, Date d) { super(a, 6000); // tick every minute title = t; initPrice = ip; currentPrice = initPrice; deltaP = initPrice - mp; deadline = d.getTime(); initTime = System.currentTimeMillis(); deltaT = ((deadline - initTime) > 0 ? (deadline - initTime) : 6000); } public void onStart() { // Insert the book in the catalogue of books available for sale catalogue.put(title, this); super.onStart(); } public void onTick() { long currentTime = System.currentTimeMillis(); if (currentTime > deadline) { // Deadline expired myGui.notifyUser("Cannot sell book " + title); catalogue.remove(title); stop(); } else { // Compute the current price long elapsedTime = currentTime - initTime; currentPrice = (int) Math.round(initPrice - 1.0 * deltaP * (1.0 * elapsedTime / deltaT)); } } public int getCurrentPrice() { return currentPrice; } } /** * Section 4.3.3 , page 67. Inner class CallForOfferServer. This is the * behaviour used by Book-seller agents to serve incoming call for offer * from buyer agents. If the indicated book is in the local catalogue, the * seller agent replies with a PROPOSE message specifying the price. * Otherwise a REFUSE message is sent back. **/ private class CallForOfferServer extends CyclicBehaviour { private MessageTemplate mt = MessageTemplate .MatchPerformative(ACLMessage.CFP); public void action() { ACLMessage msg = myAgent.receive(mt); if (msg != null) { // CFP Message received. Process it String title = msg.getContent(); myGui.notifyUser("Received Proposal to buy " + title); ACLMessage reply = msg.createReply(); PriceManager pm = (PriceManager) catalogue.get(title); if (pm != null) { // The requested book is available for sale. Reply with the // price reply.setPerformative(ACLMessage.PROPOSE); reply.setContent(String.valueOf(pm.getCurrentPrice())); } else { // The requested book is NOT available for sale. reply.setPerformative(ACLMessage.REFUSE); } myAgent.send(reply); myGui.notifyUser(pm != null ? "Sent Proposal to sell at " + reply.getContent() : "Refused Proposal as the book is not for sale"); } else { block(); } } } // End of inner class CallForOfferServer /** * Inner class PurchaseOrdersServer. This is the behaviour used by * Book-seller agents to serve incoming offer acceptances (i.e. purchase * orders) from buyer agents. The seller agent removes the purchased book * from its catalogue and replies with an INFORM message to notify the buyer * that the purchase has been sucesfully completed. */ private class PurchaseOrderServer extends CyclicBehaviour { private MessageTemplate mt = MessageTemplate .MatchPerformative(ACLMessage.ACCEPT_PROPOSAL); public void action() { ACLMessage msg = myAgent.receive(mt); if (msg != null) { // ACCEPT_PROPOSAL Message received. Process it String title = msg.getContent(); myGui.notifyUser("Received ACCEPT_PROPOSAL to purchase " + title); ACLMessage reply = msg.createReply(); PriceManager pm = (PriceManager) catalogue.get(title); if (pm != null) { // removes the purchased book from its catalogue catalogue.remove(title); reply.setPerformative(ACLMessage.INFORM); pm.stop(); } else { // The requested book is NOT available for sale. reply.setPerformative(ACLMessage.FAILURE); } myAgent.send(reply); myGui.notifyUser(pm != null ? "The book " + title + " has been sold at price = " + pm.getCurrentPrice() : "The book is not exist."); } else { block(); } } } // End of inner class PurchaseOrdersServer }
package com.leejay.booktrading.buyer;
public interface BookBuyerGui {
void setAgent(BookBuyerAgent a);
void show();
void hide();
void notifyUser(String message);
void dispose();
}
BookBuyerGuiImpl.javaBookSellerGui.javapackage com.leejay.booktrading.buyer; import jade.gui.TimeChooser; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import java.util.Date; /** J2SE (Swing-based) implementation of the GUI of the agent that tries to buy books on behalf of its user */ public class BookBuyerGuiImpl extends JFrame implements BookBuyerGui { private BookBuyerAgent myAgent; private JTextField titleTF, desiredCostTF, maxCostTF, deadlineTF; private JButton setDeadlineB; private JButton setCCB, buyB, resetB, exitB; private JTextArea logTA; private Date deadline; public BookBuyerGuiImpl() { super(); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { myAgent.doDelete(); } } ); JPanel rootPanel = new JPanel(); rootPanel.setLayout(new GridBagLayout()); rootPanel.setMinimumSize(new Dimension(330, 125)); rootPanel.setPreferredSize(new Dimension(330, 125)); /////////// // Line 0 /////////// JLabel l = new JLabel("Book to buy:"); l.setHorizontalAlignment(SwingConstants.LEFT); GridBagConstraints gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3); rootPanel.add(l, gridBagConstraints); titleTF = new JTextField(64); titleTF.setMinimumSize(new Dimension(222, 20)); titleTF.setPreferredSize(new Dimension(222, 20)); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = 3; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(titleTF, gridBagConstraints); /////////// // Line 1 /////////// /*l = new JLabel("Best cost:"); l.setHorizontalAlignment(SwingConstants.LEFT); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3); rootPanel.add(l, gridBagConstraints); desiredCostTF = new JTextField(64); desiredCostTF.setMinimumSize(new Dimension(70, 20)); desiredCostTF.setPreferredSize(new Dimension(70, 20)); desiredCostTF.setEditable(false); //FIXME just for this example gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(desiredCostTF, gridBagConstraints);*/ l = new JLabel("Max cost:"); l.setHorizontalAlignment(SwingConstants.LEFT); l.setMinimumSize(new Dimension(70, 20)); l.setPreferredSize(new Dimension(70, 20)); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3); rootPanel.add(l, gridBagConstraints); maxCostTF = new JTextField(64); maxCostTF.setMinimumSize(new Dimension(70, 20)); maxCostTF.setPreferredSize(new Dimension(70, 20)); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(maxCostTF, gridBagConstraints); /////////// // Line 2 /////////// l = new JLabel("Deadline:"); l.setHorizontalAlignment(SwingConstants.LEFT); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3); rootPanel.add(l, gridBagConstraints); deadlineTF = new JTextField(64); deadlineTF.setMinimumSize(new Dimension(146, 20)); deadlineTF.setPreferredSize(new Dimension(146, 20)); deadlineTF.setEnabled(false); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(deadlineTF, gridBagConstraints); setDeadlineB = new JButton("Set"); setDeadlineB.setMinimumSize(new Dimension(70, 20)); setDeadlineB.setPreferredSize(new Dimension(70, 20)); setDeadlineB.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { Date d = deadline; if (d == null) { d = new Date(); } TimeChooser tc = new TimeChooser(d); if (tc.showEditTimeDlg(BookBuyerGuiImpl.this) == TimeChooser.OK) { deadline = tc.getDate(); deadlineTF.setText(deadline.toString()); } } } ); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(setDeadlineB, gridBagConstraints); /*setCCB = new JButton("Set CreditCard"); setCCB.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { String cc = JOptionPane.showInputDialog(BookBuyerGuiImpl.this, "Insert the Credit Card number"); if (cc != null && cc.length() > 0) { myAgent.setCreditCard(cc); } else { JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "Invalid Credit Card number", "WARNING", JOptionPane.WARNING_MESSAGE); } } } ); //setCCB.setMinimumSize(new Dimension(70, 20)); //setCCB.setPreferredSize(new Dimension(70, 20)); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 3; gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new Insets(5, 3, 0, 3); rootPanel.add(setCCB, gridBagConstraints);*/ rootPanel.setBorder(new BevelBorder(BevelBorder.LOWERED)); getContentPane().add(rootPanel, BorderLayout.NORTH); logTA = new JTextArea(); logTA.setEnabled(false); JScrollPane jsp = new JScrollPane(logTA); jsp.setMinimumSize(new Dimension(400, 200)); jsp.setPreferredSize(new Dimension(400, 200)); JPanel p = new JPanel(); p.setBorder(new BevelBorder(BevelBorder.LOWERED)); p.add(jsp); getContentPane().add(p, BorderLayout.CENTER); p = new JPanel(); buyB = new JButton("Buy"); buyB.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { String title = titleTF.getText(); int desiredCost = -1; int maxCost = -1; if (title != null && title.length() > 0) { if (deadline != null && deadline.getTime() > System.currentTimeMillis()) { try { //desiredCost = Integer.parseInt(desiredCostTF.getText()); try { maxCost = Integer.parseInt(maxCostTF.getText()); // if (maxCost >= desiredCost) { // myAgent.purchase(title, desiredCost, maxCost, deadline.getTime()); myAgent.purchase(title, maxCost, deadline); notifyUser("PUT FOR BUY: "+title+" at max "+maxCost+" by "+deadline); //} //else { // Max cost < desiredCost //JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "Max cost must be greater than best cost", "WARNING", JOptionPane.WARNING_MESSAGE); //} } catch (Exception ex1) { // Invalid max cost JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "Invalid max cost", "WARNING", JOptionPane.WARNING_MESSAGE); } } catch (Exception ex2) { // Invalid desired cost JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "Invalid best cost", "WARNING", JOptionPane.WARNING_MESSAGE); } } else { // No deadline specified JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "Invalid deadline", "WARNING", JOptionPane.WARNING_MESSAGE); } } else { // No book title specified JOptionPane.showMessageDialog(BookBuyerGuiImpl.this, "No book title specified", "WARNING", JOptionPane.WARNING_MESSAGE); } } } ); resetB = new JButton("Reset"); resetB.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { titleTF.setText(""); desiredCostTF.setText(""); maxCostTF.setText(""); deadlineTF.setText(""); deadline = null; } } ); exitB = new JButton("Exit"); exitB.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { myAgent.doDelete(); } } ); buyB.setPreferredSize(resetB.getPreferredSize()); exitB.setPreferredSize(resetB.getPreferredSize()); p.add(buyB); p.add(resetB); p.add(exitB); p.setBorder(new BevelBorder(BevelBorder.LOWERED)); getContentPane().add(p, BorderLayout.SOUTH); pack(); setResizable(false); } public void setAgent(BookBuyerAgent a) { myAgent = a; setTitle(myAgent.getName()); } public void notifyUser(String message) { logTA.append(message+"\n"); } }
package com.leejay.booktrading.seller;
public interface BookSellerGui {
void setAgent(BookSellerAgent a);
void show();
void hide();
void notifyUser(String message);
void dispose();
}
BookSellerGuiImpl.java
package com.leejay.booktrading.seller;
import jade.gui.TimeChooser;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Date;
/**
This is the GUI of the agent that tries to sell books on behalf of its user
*/
public class BookSellerGuiImpl extends JFrame implements BookSellerGui {
private BookSellerAgent myAgent;
private JTextField titleTF, desiredPriceTF, minPriceTF, deadlineTF;
private JButton setDeadlineB;
private JButton setCCB, sellB, resetB, exitB;
private JTextArea logTA;
private Date deadline;
public void setAgent(BookSellerAgent a) {
myAgent = a;
setTitle(myAgent.getName());
}
public BookSellerGuiImpl() {
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myAgent.doDelete();
}
} );
JPanel rootPanel = new JPanel();
rootPanel.setLayout(new GridBagLayout());
rootPanel.setMinimumSize(new Dimension(330, 125));
rootPanel.setPreferredSize(new Dimension(330, 125));
///////////
// Line 0
///////////
JLabel l = new JLabel("Book to sell:");
l.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
rootPanel.add(l, gridBagConstraints);
titleTF = new JTextField(64);
titleTF.setMinimumSize(new Dimension(222, 20));
titleTF.setPreferredSize(new Dimension(222, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
rootPanel.add(titleTF, gridBagConstraints);
///////////
// Line 1
///////////
l = new JLabel("Best price:");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
rootPanel.add(l, gridBagConstraints);
desiredPriceTF = new JTextField(64);
desiredPriceTF.setMinimumSize(new Dimension(70, 20));
desiredPriceTF.setPreferredSize(new Dimension(70, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
rootPanel.add(desiredPriceTF, gridBagConstraints);
l = new JLabel("Min price:");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setMinimumSize(new Dimension(70, 20));
l.setPreferredSize(new Dimension(70, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
rootPanel.add(l, gridBagConstraints);
minPriceTF = new JTextField(64);
minPriceTF.setMinimumSize(new Dimension(70, 20));
minPriceTF.setPreferredSize(new Dimension(70, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
rootPanel.add(minPriceTF, gridBagConstraints);
///////////
// Line 2
///////////
l = new JLabel("Deadline:");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
rootPanel.add(l, gridBagConstraints);
deadlineTF = new JTextField(64);
deadlineTF.setMinimumSize(new Dimension(146, 20));
deadlineTF.setPreferredSize(new Dimension(146, 20));
deadlineTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
rootPanel.add(deadlineTF, gridBagConstraints);
setDeadlineB = new JButton("Set");
setDeadlineB.setMinimumSize(new Dimension(70, 20));
setDeadlineB.setPreferredSize(new Dimension(70, 20));
setDeadlineB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Date d = deadline;
if (d == null) {
d = new Date();
}
TimeChooser tc = new TimeChooser(d);
if (tc.showEditTimeDlg(BookSellerGuiImpl.this) == TimeChooser.OK) {
deadline = tc.getDate();
deadlineTF.setText(deadline.toString());
}
}
} );
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
rootPanel.add(setDeadlineB, gridBagConstraints);
rootPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(rootPanel, BorderLayout.NORTH);
logTA = new JTextArea();
logTA.setEnabled(false);
JScrollPane jsp = new JScrollPane(logTA);
jsp.setMinimumSize(new Dimension(400, 200));
jsp.setPreferredSize(new Dimension(400, 200));
JPanel p = new JPanel();
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
p.add(jsp);
getContentPane().add(p, BorderLayout.CENTER);
p = new JPanel();
sellB = new JButton("Sell");
sellB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
String title = titleTF.getText();
int desiredPrice = -1;
int minPrice = -1;
if (title != null && title.length() > 0) {
if (deadline != null && deadline.getTime() > System.currentTimeMillis()) {
try {
desiredPrice = Integer.parseInt(desiredPriceTF.getText());
try {
minPrice = Integer.parseInt(minPriceTF.getText());
if (minPrice <= desiredPrice) {
// myAgent.addToCatalogue(title, desiredPrice, minPrice, deadline.getTime());
myAgent.putForSale(title, desiredPrice, minPrice, deadline);
notifyUser("PUT FOR SALE: "+title+" between "+desiredPrice+" and "+minPrice+" by "+deadline);
}
else {
// minPrice > desiredPrice
JOptionPane.showMessageDialog(BookSellerGuiImpl.this, "Min price must be cheaper than best price", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
catch (Exception ex1) {
// Invalid max cost
JOptionPane.showMessageDialog(BookSellerGuiImpl.this, "Invalid min price", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
catch (Exception ex2) {
// Invalid desired cost
JOptionPane.showMessageDialog(BookSellerGuiImpl.this, "Invalid best price", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// No deadline specified
JOptionPane.showMessageDialog(BookSellerGuiImpl.this, "Invalid deadline", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// No book title specified
JOptionPane.showMessageDialog(BookSellerGuiImpl.this, "No book title specified", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
} );
resetB = new JButton("Reset");
resetB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
titleTF.setText("");
desiredPriceTF.setText("");
minPriceTF.setText("");
deadlineTF.setText("");
deadline = null;
}
} );
exitB = new JButton("Exit");
exitB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
myAgent.doDelete();
}
} );
sellB.setPreferredSize(resetB.getPreferredSize());
exitB.setPreferredSize(resetB.getPreferredSize());
p.add(sellB);
p.add(resetB);
p.add(exitB);
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(p, BorderLayout.SOUTH);
pack();
setResizable(false);
}
public void notifyUser(String message) {
logTA.append(message+"\n");
}
}