Create a Project based on P2P/PubSub with OODB and DataMining

Joe

Thành viên VIP
21/1/13
3,074
1,344
113
(Continue of HERE)

Create a Project based on P2P/PubSub with OODB and DataMining

I have explained to you in the previous lectures how to design and to build an effective Messaging System without having to license any MQ heavyweight à la IBM-MQ, nor Rabbit MQ. With three little objects: MessageSender and MessageListener in coordination with a selector ModelWorker. Further, I have showed you how local Images are processed and made independent from the physical storing location (only when the image cannot be accessed by a link).

It's clear that Sender and Listener are either Publisher or Subscriber. Because the messages arrive whenever they were broadcast, and the Subscribers cannot stand by all the time to receive and to check for the contents whether they are the expected messages or not. That delays everything and could cause some loss of messages. The most optimal way is to have someone who acts as the Selector and accepts or ignores the messages and then performs the necessary work depending on the message content.

1) The Publisher or MessageSender
Java:
// Joe Nartca (C)
public class MessageSender implements Runnable {
  public MessageSender(Parms P) {
    this.P = P;
  }
  public synchronized void broadcast(byte[] msg) {
    msgLst.add(msg);
  }
  public void halt() {
    loop = false;
  }
  public void run( ) {
    try (MulticastSocket mcs = new MulticastSocket(P.port)){
      InetAddress group = InetAddress.getByName(P.host);
      while (loop) {
        while (msgLst.size() > 0) {
          byte[] msg = msgLst.remove(0);
          mcs.send(new DatagramPacket(msg, msg.length, group, P.port));
        }
        java.util.concurrent.TimeUnit.NANOSECONDS.sleep(10);
      }
    } catch (Exception ex) { }
  }
  private Parms P;
  private volatile boolean loop = true;
  private volatile List<byte[]> msgLst = Collections.synchronizedList(new ArrayList<byte[]>());
}
2) The Subscriber or MessageListener
Java:
// Joe T. Nartca
public class MessageListener implements Runnable {
  public MessageListener(Parms P) {
    this.P = P;
  }
  public void halt() {
    loop = false;
  }
  public void run() {
    try (MulticastSocket listener = new MulticastSocket(P.port)){
       listener.joinGroup(InetAddress.getByName(P.host));
       while (loop) { // max. paket 8 KB
         DatagramPacket packet = new DatagramPacket(new byte[8192], 8192);
         listener.receive(packet); // wait for the incoming msg
         P.pool.submit(new ModelWorker(P, packet));
       }
    } catch (Exception ex) { }
  }
  private Parms P;
  private volatile boolean loop = true;
}
3) The Worker or the Selector - ModelWorker
Java:
// Joe Nartca (C)
// message format: netID!dbName!key!idx!mode
// P.tables[] and P.models[]: index 0: item, 1:order, 2: bill, 3: account, 4: itemProduct, 5: human
// idx: 0...5 index of Models/Tables. 6...9: reserved
//      10 for 0/4, 11 for 1/3, 12 for 2/3, 13 for 1/2/3
public class ModelWorker implements Runnable {
  public ModelWorker(Parms P, java.net.DatagramPacket packet) {
    msg = (new String(packet.getData(), 0, packet.getLength())).split("\t");
    this.P = P;
  }
  public void run() {
    String dbName = msg[1];
    idx = Integer.parseInt(msg[3]);
    if (dbName.equals(P.dbHResource) && P.cate < 4 ||
        dbName.equals(P.dbInvoice) && (P.cate == 0 || P.cate == 5)) return;
    int mode = Integer.parseInt(msg[4]);
    String key = msg[2];
    try { // synchronized
      TimeUnit.MICROSECONDS.sleep(P.time);
    } catch (Exception et) { }
    // sales, multiple keys ?
    if (key.charAt(0) == '\r') {
      String[][] rows = P.models[0].getRows();
      String[] keys = key.substring(1).split("\r");
      for (String k:keys) {
        Object obj = P.oodb.readLock(dbName, k);
        int i = P.models[0].getRowAt(k);
        rows[i] = ((Item)obj).toArray();
      }
      P.models[0].updateModel(rows);
      if (P.cate == 4) P.models[4].updateModel(rows);
      return;
    }
    int ix[] = null;
    if (idx == 10) { // Model/JTable 0/4
      if (P.cate == 4) ix = new int[] { 0, 4, -1 };
      if (P.cate == 0) ix = new int[] { 0, -1, -1 };
    } else if (idx == 11) { // Model/JTable 1/3
      if (P.cate == 3 || P.cate == 4) ix = new int[] { 1, 3, -1 };
      if (P.cate == 1) ix = new int[] { 1, -1, -1 };
    } else if (idx == 12) { // Model/JTable 2/3
      if (P.cate == 3 || P.cate == 4) ix = new int[] { 2, 3, -1 };
      if (P.cate == 2) ix = new int[] { 2, -1, -1 };
    } else if (idx == 13) { // Model/JTable 1/2/3
      if (P.cate == 3 || P.cate == 4) ix = new int[] { 1, 2, 3 };
      if (P.cate == 2) ix = new int[] { -1, 2, -1 };
      if (P.cate == 1) ix =  new int[] { 1, -1, -1 };
    } else if (idx >= 0 && idx < 6) { // 0/1/2/3/4/5
      ix = new int[] { idx, -1, -1 };
    }
    if (ix == null) {
      Utilities.errorLog(P, "**** ModelWorker. Unknown Index: "+idx);
      return;
    }
    int r;
    if (mode == 2) {
      if (ix[0] >= 0) {
        r = P.models[ix[0]].getRowAt(key);
        P.models[ix[0]].removeRow(r);
        if (P.icon && dbName.equals(P.dbItem)) P.iPanel.delIcon(r);
      }
      if (ix[1] >= 0) {
        r = P.models[ix[1]].getRowAt(key);
        P.models[ix[1]].removeRow(r);
      }
      if (ix[2] >= 0) {
        r = P.models[ix[2]].getRowAt(key);
        P.models[ix[2]].removeRow(r);
      }
      return;
    }
    Object obj = P.oodb.readLock(dbName, key);
    if (mode == 0) {
      if (ix[0] >= 0) {
        idx = ix[0];
        r = P.models[ix[0]].getRowAt(key);
        P.models[ix[0]].updateRow(getRow(obj), r);
        if (P.icon && dbName.equals(P.dbItem)) P.iPanel.updateIcon(r);
      }
      if (ix[1] >= 0) {
        idx = ix[1];
        r = P.models[ix[1]].getRowAt(key);    
        P.models[ix[1]].updateRow(getRow(obj), r);
      }
      if (ix[2] >= 0) {
        idx = ix[2];
        r = P.models[ix[2]].getRowAt(key);
        P.models[ix[2]].updateRow(getRow(obj), r);
      }
      return;
    }
    if (mode == 1) {
      if (ix[0] >= 0) {
        idx = ix[0];
        r = P.models[ix[0]].getRowCount();
        P.models[ix[0]].addRow(getRow(obj));
      }
      if (ix[1] >= 0) {
        idx = ix[1];
        r = P.models[ix[1]].getRowCount();
        P.models[ix[1]].addRow(getRow(obj));
      }
      if (ix[2] >= 0) {
        idx = ix[2];
        r = P.models[ix[2]].getRowCount();
        P.models[ix[2]].addRow(getRow(obj));
      }
      if (P.icon && dbName.equals(P.dbItem)) P.iPanel.addIcon( );
      return;
    }
    Utilities.errorLog(P, "**** ModelWorker. Unknown Mode: "+mode);
  }
  //
  private String[] getRow(Object obj) {
    if (obj instanceof Item)
      return ((Item)obj).toArray();
    if (obj instanceof Invoice) {  // 1, 2, 3
      if (idx == 1) return ((Invoice)obj).toOrderArray();
      if (idx == 2) return ((Invoice)obj).toBillingArray();
      return ((Invoice)obj).toArray();
    }
    if (obj instanceof HumanResource) return ((HumanResource)obj).toArray();
    return null;
  }
  private int idx;
  private Parms P;
  private String[] msg;
}
The Project is an Online Boutique Model. The articles are sold either directly by the staff, or bought online by registered clients. Any change (purchased items, paying, etc.) will be processed directly on the site, and then an invoice is created and stored in the OODB before the change will be published (broadcast() method) and the subscribed clients become the update almost instantly -worked out by the ModelWorker.

The Invoice: a serialized POJO
Java:
// Joe Nartca (c)
public class Invoice implements java.io.Serializable {
  private static final long serialVersionUID = 9012L;
  /**
  Constructor
  **/
  public Invoice(String date) {
    this.date = date;
  }
  public String[] toArray() {
    return new String[] { date, ""+saleItems.size(), ""+orderItems.size(), getPaying(),
                          done == 0?"Pending":"Done", uID };
  }
  public String[] toBillingArray() {
    return new String[] { date, ""+saleItems.size(), getPaying(), billDone == 0?"Pending":"Done", uID };
  }
  public void setCard(String card) {
    this.card = card;
  }
  public void setCustomer(int ext) {
    this.ext = ext;
  }
  public void setPaying(int pay) { // 0: cash, 1: bank card, otherwise credit card
    if (pay < 0 || pay > 1) cash = 2;
    else cash = pay;
  }
  public String[] toOrderArray() {
    return new String[] { date, ""+orderItems.size(), getPaying(), orderDone == 0?"Pending":"Done", uID };
  }
  public void putProfits(double profit) {
    profits.add(profit);
  }
  public void putSale(String item, String uID, int n) {
    sales.add(n);
    this.uID = uID;
    saleItems.add(item);
  }
  public void putOrder(String item, String uID, int n) {
    stock.add(n);
    this.uID = uID;
    orderItems.add(item);
  }
  public void removeOrder() {
    if (orderDone == 1 || orderItems.size() == 0) delOrder = 1;
  }
  public void removeBill() {
    if (billDone == 1) delBill = 1;
  }
  public void setBillDone() {
    billDone = 1;
    if (orderDone == 1 || orderItems.size() == 0) done = 1;
  }
  public void setOrderDone() {
    orderDone = 1;
    orderItems.clear();
    if (billDone == 1) done = 1;
  }
  public String getDate() {
    return date;
  }
  public String getOwner() {
    return uID;
  }
  public boolean isOrderDone() {
    return orderDone == 1;
  }
  public boolean isOrderRemoved() {
    return delOrder == 1;
  }
  public boolean isBillRemoved() {
    return delBill == 1;
  }
  public boolean isBillDone() {
    return billDone == 1;
  }
  public List<Integer> getSales() {
    return sales;
  }
  public List<Integer> getOrder() {
    return stock;
  }
  public List<String> getOrderList() {
    return orderItems;
  }
  public List<String> getSalesList() {
    return saleItems;
  }
  public List<Double> getProfitsList() {
    return profits;
  }
  public String getCard() {
    return card;
  }
  public String getPaying() {
    if (cash == 0) return "Cash";
    else if (cash == 1) return "BankCard";
    return "CreditCard";
  }
  public int getNumberOfOrders() {
    return orderItems.size();
  }
  public int getNumberOfSales() {
    return saleItems.size();
  }
  public boolean isCustomer() {
    return ext == 1;
  }
  //
  private String date, uID, card;
  private List<Integer> sales = new ArrayList<>();
  private List<Integer> stock = new ArrayList<>();
  private List<Double> profits = new ArrayList<>();
  private List<String> saleItems = new ArrayList<>();
  private List<String> orderItems = new ArrayList<>();
  private int delOrder = 0, delBill = 0, billDone = 0, ext = 0, orderDone = 0, done = 0, cash = 0;
}
The GUI for the registered Clients and the Sales-staff can be displayed in a JTable with customized AbstractTableModel:
salesJTable.png
JTable with customized AbstractTableModel

NOTE: the prices of all articles are imaginary, but their images are the public links on the WEB and real. Tons of thanks to those who posted these images.

And when an article was selected (clicked on) an image of this article is popped up so that the clients could see the article as following:
SalesSelectedItem.png
Selected Item

Or a Panel with icons of the articles.
salesIcons.png
JPanel with Icons

And a selected article is presented as following:
onIcon.png
Selected Icon

In case that the number of articles exceeds the JPanel area NEXT and BACK Button will be presented so that the clients can move fore and back with a click on the button.

nextPage.png

previousPage.png

(continue HERE)
 
Sửa lần cuối: