Skip to content

5. Appendices

5.1. Code from the [istia.st.articles.dao] package

5.1.1. IArticlesDao

package istia.st.articles.dao;

import istia.st.articles.domain.Article;
import java.util.List;

/**
 * @author serge
 *
 */
public interface IArticlesDao {

  /**
   * @return: list of all articles
   */
  public List getAllArticles();

  /**
   * @param anArticle:
   *          : the article to add
   */
  public int addArticle(Article anArticle);

  /**
   * @param articleId:
   *          ID of the article to delete
   */
  public int deleteArticle(int articleId);

  /**
   * @param article:
   *          the article to modify
   */
  public int modifyArticle(Article anArticle);

  /**
   * @param articleId:
   *          : ID of the article being searched for
   * @return: the found article or null
   */
  public Article getArticleById(int articleId);

  /**
   * clears the article table
   */
  public void clearAllArticles();


  /**
   *
   * @param itemId ID of the item whose stock is being updated
   * @param movement value to add to stock (signed value)
   */
  public int updateItemStock(int itemId, int movement);
}

5.1.2. ArticlesDaoSqlMap

package istia.st.articles.dao;

import java.io.*;
import java.sql.*;
import java.util.*;
import com.ibatis.common.resources.*;
import com.ibatis.sqlmap.client.*;
import istia.st.articles.domain.*;
import istia.st.articles.exception.*;

/**
 * @author ST-ISTIA
 *
 */
public class ArticlesDaoSqlMap
    implements IArticlesDao {

  /**
   * sqlMap object providing access to data in a DBMS
   * is built from a configuration file
   * executes SQL queries that are also stored in a configuration file
   */
  private SqlMapClient sqlMap = null;

  /**
   *
   * @return the sqlMap object for data access
   */
  public SqlMapClient getSqlMap() {
    return sqlMap;
  }

  /**
   *
   * @param sqlMap the sqlMap object for data access
   */
  public void setSqlMap(SqlMapClient sqlMap) {
    this.sqlMap = sqlMap;
  }

  /**
   *
   * @param sqlMapConfigFileName the name of the SqlMap configuration file
   * @throws UncheckedAccessArticlesException if any issues occur
   */
  public ArticlesDaoSqlMap(String sqlMapConfigFileName) {
    Reader reader = null;
    UncheckedAccessArticlesException ex = null;
    try {
      reader = Resources.getResourceAsReader(sqlMapConfigFileName);
      sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
    }
    catch (Exception ex1) {
      ex = new UncheckedAccessArticlesException(
          "Error constructing the [sqlMap] object from the configuration file ["
          + sqlMapConfigFileName + "] : ", ex1);
    }
    finally {
      try {
        reader.close();
      }
      catch (Exception ex2) {
        if (ex != null) {
          ex = new UncheckedAccessArticlesException(
              "Error closing the [reader] object from the configuration file ["
              + sqlMapConfigFileName + "] : ", ex2);
        }
      }
    }
    // Should an exception be thrown?
    if (ex != null) {
      throw ex;
    }
  }

  /**
   * @return a list of all items of type Article
   */
  public synchronized List getAllArticles() {
    try {
      return sqlMap.queryForList("getAllArticles", null);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Failed to retrieve all articles: [" + ex + "]", ex);
    }
  }

  /**
   * @param anArticle the article to add
   * @return the number of items added
   * @throws UncheckedAccessArticlesException if failed
   */

  public synchronized int addArticle(Article anArticle) {
    try {
      // prepare the parameters
      Map parameters = new HashMap(5);
      parameters.put("id", new Integer(article.getId()));
      parameters.put("name", unArticle.getName());
      parameters.put("price", new Double(anItem.getPrice()));
      parameters.put("currentStock", new Integer(anItem.getCurrentStock()));
      parameters.put("minStock", new Integer(anItem.getMinStock()));
      // execute the query
      return sqlMap.update("insertArticle", parameters);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Failed to add article [" + unArticle + "] : [" + ex + "]",
          ex);
    }
  }

  /**
   * @param idArticle ID of the article to delete
   * @return the number of articles deleted
   * @throws UncheckedAccessArticlesException if failed
   */

  public synchronized int deleteArticle(int articleId) {
    try {
      // prepare the parameters
      Map parameters = new HashMap(1);
      parameters.put("id", new Integer(articleId));
      // execute the query
      return sqlMap.update("deleteArticle", parameters);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Error deleting article with id [" + idArticle
          + "] : [" + ex + "]", ex);
    }
  }

  /**
   * @param anArticle the modified article that should replace the old one with the same ID
   * @return the number of modified articles
   * @throws UncheckedAccessArticlesException if failed
   */

  public synchronized int modifyArticle(Article anArticle) {
    try {
      // prepare the parameters
      Map parameters = new HashMap(5);
      parameters.put("id", new Integer(article.getId()));
      parameters.put("name", unArticle.getName());
      parameters.put("price", new Double(anItem.getPrice()));
      parameters.put("currentStock", new Integer(anItem.getCurrentStock()));
      parameters.put("minStock", new Integer(anItem.getMinStock()));
      // execute the query
      return sqlMap.update("modifyArticle", parameters);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Error updating article [" + article +
          "]: ["
          + ex + "]", ex);
    }
  }

  /**
   * @param idArticle ID of the article being searched for
   * @return Article: the found article or null
   * @throws UncheckedAccessArticlesException if unsuccessful
   */

  public synchronized Article getArticleById(int articleId) {
    try {
      // prepare the parameters
      Map parameters = new HashMap(1);
      parameters.put("id", new Integer(articleId));
      // execute the query
      Article article = (Article) sqlMap.queryForObject("getArticleById",
          parameters);
      // Return the result
      return article;
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Error retrieving the article with id [" + idArticle
          + "] : [" + ex + "]", ex);
    }
  }

  /**
   * clears the article table
   * @throws UncheckedAccessArticlesException on failure
   */

  public synchronized void clearAllArticles() {
    try {
      sqlMap.update("clearAllArticles", null);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Error clearing the articles table: [" + ex +
          "",
          ex);
    }
  }

  /**
   *
   * @param percentage the percentage increase as an integer
   * @throws UncheckedAccessArticlesException on failure
   */
  public synchronized void increaseAllPrices(int percentage) {
    try {

      // prepare the parameters
      Map parameters = new HashMap(1);
      parameters.put("percentage", new Double(0.01 * percentage));
      // execute the query
      sqlMap.update("priceIncrease", parameters);
    }
    catch (SQLException ex) {
      throw new UncheckedAccessArticlesException(
          "Price increase error: [" + ex + "]", ex);
    }
  }

  /**
   * test method
   */
  public void badOperationThrowsException() {
    // artificially throws an exception
    throw new UncheckedAccessArticlesException();
  }

  /**
   *
   * @param articles Article[] list of articles to insert in a single transaction
   * @throws UncheckedAccessArticlesException if failed
   */
  public synchronized void doInsertionsInTransaction(Article[] articles) {
    // insert all articles as a single unit
    UncheckedAccessArticlesException ex = null;
    int i = 0;
    Connection connection = null;
    try {
      // Start the transaction
      sqlMap.startTransaction();
      // perform the inserts
      for (; i < articles.length; i++) {
        addItem(items[i]);
      }
      // Commit the transaction
      sqlMap.commitTransaction();
    }
    catch (Exception ex1) {
      // wrap the exception
      ex = new UncheckedAccessArticlesException(
          "doInsertionsInTransaction, database access error: [" + ex1 +
          "",
          ex1);
    }
    finally {
      try {
        sqlMap.endTransaction();
      }
      catch (SQLException ex2) {
        if (ex != null) {
          ex = new UncheckedAccessArticlesException(
              "doInsertionsInTransaction, close failed: [" + ex2 + "]", ex2);
        }
      }
    }
    // Should an exception be thrown?
    if (ex != null) {
      throw ex;
    }
  }

  /**
   *
   * @param idArticle ID of the item whose stock is being updated
   * @param movement stock movement
   */
  public synchronized int updateItemStock(int itemId, int movement) {
    try {
      // Prepare the parameters
      Map parameters = new HashMap(2);
      parameters.put("id", new Integer(itemId));
      parameters.put("movement", new Integer(movement));
      // execute the query
      return sqlMap.update("updateItemStock", parameters);
    }
    catch (SQLException e1) {
      throw new UncheckedAccessArticlesException(
          "Error updating stock [idArticle=" + idArticle +
          ", movement=" + movement + "] : [" + e1 + "]", e1);
    }
  }
}

5.1.3. Article

package istia.st.articles.dao;
import istia.st.articles.exception.UncheckedAccessArticlesException;

/**
 * @author ST - ISTIA
 *  
 */
public class Article {
  private int id;
  private String name;
  private double price;
  private int currentStock;
  private int minimumStock;

  /**
   * default constructor
   */
  public Item() {
  }

  public Article(int id, String name, double price, int currentStock,
      int minimumStock) {
    // Initialize instance attributes
    setId(id);
    setName(name);
    setPrice(price);
    setCurrentStock(currentStock);
    setMinStock(minStock);
  }

    // getters - setters
  public int getId() {
    return id;
  }

  public void setId(int id) {
    // Is the ID valid?
    if (id < 0)
      throw new UncheckedAccessArticlesException("Invalid id[" + id + "]");
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    // Is the name valid?
    if(name == null || name.trim().equals("")){
      throw new UncheckedAccessArticlesException("The name is [null] or empty");
    }
    this.name = name;
  }

  public double getPrice() {
    return price;
  }

  public void setPrice(double price) {
    // Is the price valid?
    if(price < 0) throw new UncheckedAccessArticlesException("Invalid price [" + price + "]");
    this.price = price;
  }

  public int getCurrentStock() {
    return currentStock;
  }

  public void setCurrentStock(int currentStock) {
    // Is the stock valid?
    if (currentStock < 0)
      throw new UncheckedAccessArticlesException("currentStock[" + currentStock + "] is invalid");
    this.currentStock = currentStock;
  }

  public int getMinimumStock() {
    return stockMinimum;
  }

  public void setStockMinimum(int stockMinimum) {
    // Is the stock valid?
    if (stockMinimum < 0)
      throw new UncheckedAccessArticlesException("stockMinimum[" + stockMinimum + "] is invalid");
    this.stockMinimum = stockMinimum;
  }

  public String toString() {
    return "[" + id + "," + name + "," + price + "," + currentStock + ","
        + stockMinimum + "]";
  }
}

5.2. The package [istia.st.articles.domain]

5.2.1. IArticlesDomain

package istia.st.articles.domain;

import java.util.ArrayList;
import java.util.List;

public interface IArticlesDomain {
  public void buy(ShoppingCart shoppingCart);
  public List getAllArticles();
  public Article getArticleById(int id);
  public ArrayList getErrors();
}

5.2.2. Purchase

package istia.st.articles.domain;

public class Purchase {

  /**
   * the purchased item
   */
  private Article article;
  /**
   * the quantity purchased
   */
  private int qty;
  /**
   * @return Returns the amount to be paid for the purchase
   */
  public double getTotal() {
    return item.getPrice() * qty;
  }

  /**
   * 
   * @param item
   *          s the purchased item
   * @param qty
   *          the quantity purchased
   */
  public Purchase(Article item, int qty) {
    this.item = item;
    this.qty = qty;
  }

  /**
   * @return Returns the purchased item
   */
  public Item getItem() {
    return item;
  }

  /**
   * @param article
   *          s the purchased item
   */
  public void setArticle(Article article) {
    this.article = article;
  }

  /**
   * @return Returns the quantity purchased
   */
  public int getQuantity() {
    return qty;
  }

  /**
   * @param qte
   *          s the quantity purchased
   */
  public void setQty(int qty) {
    this.qte = qte;
  }

  /**
   * @return string representing the purchase
   */
  public String toString() {
    return "[" + this.item.toString() + "," + this.qty + "]";
  }
}

5.2.3. Cart

package istia.st.articles.domain;

import java.util.ArrayList;

public class ShoppingCart {
  /**
   * list of purchases
   */
  private ArrayList purchases = new ArrayList();

  /**
   * @return Returns the purchases.
   */
  public ArrayList getPurchases() {
    return purchases;
  }

  /**
   * adds a purchase
   * 
   * @param aPurchase
   */
  public void add(Purchase purchase) {
    // add the purchase
    // check if the item has already been purchased
    int itemId = purchase.getItem().getId();
    Item item = null;
    Purchase purchase = null;
    boolean found = false;
    for (int i = 0; !found && i < purchases.size(); i++) {
      purchase = (Purchase) purchases.get(i);
      item = (Item) purchase.getItem();
      if (item.getId() == itemId) {
        purchase.setQuantity(purchase.getQuantity() + onePurchase.getQuantity());
        found = true;
      }
    }
    // Item found?
    if (!found) {
      // Not purchased yet - add the purchase
      purchases.add(aPurchase);
    }
  }

  /**
   * 
   * @param purchaseId
   *          the ID of the purchase to remove from the cart
   */
  public void remove(int itemId) {
    // Remove the purchase with id idPurchase
    for (int i = 0; i < purchases.size(); i++) {
      if (((Purchase) purchases.get(i)).getItem().getId() == itemId) {
        purchases.remove(i);
      }
    }
  }

  /**
   * 
   * @return the total amount due
   */
  public double getTotal() {
    // calculate the total of purchases
    double total = 0;
    for (int i = 0; i < purchases.size(); i++) {
      total += ((Purchase) purchases.get(i)).getTotal();
    }
    return total;
  }

  /**
   * @return a string representing the shopping cart
   */
  public String toString() {
    return this.purchases.toString();
  }
}

5.2.4. PurchasesItems

package istia.st.articles.domain;

import java.util.ArrayList;
import java.util.List;
import istia.st.articles.dao.IArticlesDao;

public class PurchasedItems implements IArticlesDomain {

    private IArticlesDao articlesDao;
    private Object synchro = new Object();
    private ArrayList errors;

    /**
     * @return Returns the errors.
     */
    public ArrayList getErrors() {
        return errors;
    }

    /**
     * 
     * @param articlesDao
     *          the data access service
     */
    public PurchaseItems(IArticlesDao articlesDao) {
        this.articlesDao = articlesDao;
    }

    public List getAllArticles() {
        return articlesDao.getAllArticles();
    }

    public Article getArticleById(int id) {
        return articlesDao.getArticleById(id);
    }

    public void buy(Cart cart) {
        // iterate through the purchases
        ArrayList purchases = cart.getPurchases();
        errors = new ArrayList();
        Item item = null;
        Purchase purchase = null;
        for (int i = purchases.size() - 1; i >= 0; i--) {
            // retrieve the purchase
            purchase = (Purchase) purchases.get(i);
            // attempt to update the item's stock in the database
            int nbarticles =
                articlesDao.updateItemStock(
                    purchase.getArticle().getId(),
                    -purchase.getQuantity());
            // Was it successful?
            if (nbarticles != 0) {
                purchases.remove(i);
            } else {
                errors.add(
                    "Purchase item ["
                        + purchase.getArticle()
                        + ","
                        + purchase.getQty()
                        + "] not possible - Check stock");
            }
        }
    }
}

5.3. The package [istia.st.articles.exception]

package istia.st.articles.exception;

public class UncheckedAccessArticlesException
    extends RuntimeException {
  public UncheckedAccessArticlesException() {
    super();
  }

  public UncheckedAccessArticlesException(String mesg) {
    super(mesg);
  }

  public UncheckedAccessArticlesException(String mesg, Throwable th) {
    super(mesg, th);
  }
}