Coverage Report - org.paneris.jammyjoes.shopping.ShoppingTrolley
 
Classes in this File Line Coverage Branch Coverage Complexity
ShoppingTrolley
0%
0/131
0%
0/22
1.217
 
 1  
 /*
 2  
  * $Source: /usr/cvsroot/org/paneris/melati/shopping/ShoppingTrolley.java,v $
 3  
  * $Revision: 1.15 $
 4  
  *
 5  
  * Copyright (C) 2000 Tim Joyce
 6  
  *
 7  
  * Part of Melati (http://melati.org), a framework for the rapid
 8  
  * development of clean, maintainable web applications.
 9  
  *
 10  
  * Melati is free software; Permission is granted to copy, distribute
 11  
  * and/or modify this software under the terms either:
 12  
  *
 13  
  * a) the GNU General Public License as published by the Free Software
 14  
  *    Foundation; either version 2 of the License, or (at your option)
 15  
  *    any later version,
 16  
  *
 17  
  *    or
 18  
  *
 19  
  * b) any version of the Melati Software License, as published
 20  
  *    at http://melati.org
 21  
  *
 22  
  * You should have received a copy of the GNU General Public License and
 23  
  * the Melati Software License along with this program;
 24  
  * if not, write to the Free Software Foundation, Inc.,
 25  
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
 26  
  * GNU General Public License and visit http://melati.org to obtain the
 27  
  * Melati Software License.
 28  
  *
 29  
  * Feel free to contact the Developers of Melati (http://melati.org),
 30  
  * if you would like to work out a different arrangement than the options
 31  
  * outlined here.  It is our intention to allow Melati to be used by as
 32  
  * wide an audience as possible.
 33  
  *
 34  
  * This program is distributed in the hope that it will be useful,
 35  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 36  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 37  
  * GNU General Public License for more details.
 38  
  *
 39  
  * Contact details for copyright holder:
 40  
  *
 41  
  *     Tim Joyce <timj@paneris.org>
 42  
  *     http://paneris.org/
 43  
  *     68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
 44  
  */
 45  
 
 46  
 package org.paneris.jammyjoes.shopping;
 47  
 
 48  
 import java.text.NumberFormat;
 49  
 import java.util.Enumeration;
 50  
 import java.util.Hashtable;
 51  
 import java.util.Locale;
 52  
 import java.util.Vector;
 53  
 
 54  
 import javax.servlet.http.HttpSession;
 55  
 
 56  
 import org.melati.Melati;
 57  
 import org.melati.poem.AccessPoemException;
 58  
 import org.melati.poem.AccessToken;
 59  
 import org.melati.poem.Capability;
 60  
 import org.melati.poem.PoemThread;
 61  
 import org.melati.util.InstantiationPropertyException;
 62  
 import org.paneris.jammyjoes.model.JammyjoesDatabase;
 63  
 import org.paneris.jammyjoes.util.JammyJoesUtil;
 64  
 
 65  
  /**
 66  
  * <p> A Shopping Trolley stored information in the user's Shopping Trolley.<p>
 67  
  * <p> It does this by storing itself in the session.</p>
 68  
  * <p> For this reason, the constructors are private, and you will be expected to
 69  
  * always get the Shopping Trolley using getInstance();</p>
 70  
  *
 71  
  * usage example:
 72  
  *
 73  
  * ShoppingTrolley trolley = ShoppingTrolley.getInstance(Melati melati);
 74  
  * context.put("trolley", trolley);
 75  
  *
 76  
  **/
 77  
 
 78  0
 public abstract class ShoppingTrolley {
 79  
 
 80  0
   private static String TROLLEY = "org.paneris.melati.shopping.DefaultShoppingTrolley";
 81  
   protected Locale locale;
 82  
   protected String address;
 83  
   protected String name;
 84  
   protected String tel;
 85  
   protected String town;
 86  
   protected String county;
 87  
   protected String country;
 88  
   protected String postcode;
 89  
   protected String message;
 90  
   protected String email;
 91  0
   protected boolean hasDetails = false;
 92  0
   Vector orderedItems = new Vector();
 93  0
   Hashtable items = new Hashtable();
 94  
   public MelatiShoppingConfig config;
 95  
   public Melati melati;
 96  
 
 97  
   /**
 98  
    * private Constructor to build an empty ShoppingTrolley
 99  
   **/
 100  
   protected void initialise(Melati melati, MelatiShoppingConfig config) {
 101  0
     this.config = config;
 102  0
     this.melati = melati;
 103  0
   }
 104  
 
 105  
   /**
 106  
    * public Constructor to build a trolley from some id
 107  
   **/
 108  
   public void initialise(Melati melati, MelatiShoppingConfig config, Integer id)
 109  
    throws InstantiationPropertyException {
 110  0
     initialise(melati,config);
 111  0
     load(id);
 112  0
     HttpSession session = melati.getSession();
 113  0
     session.setAttribute(name(),this);
 114  0
   }
 115  
 
 116  
   /**
 117  
    * remove any trolley from the session
 118  
    */
 119  
   public void remove(Melati melati) {
 120  0
     HttpSession session = melati.getSession();
 121  0
     session.removeAttribute(name());
 122  0
   }
 123  
 
 124  
 
 125  
   /**
 126  
    * Returns the single instance, creating one if it can't be found.
 127  
    */
 128  
   public static synchronized ShoppingTrolley getInstance(Melati melati, MelatiShoppingConfig config)
 129  
    throws InstantiationPropertyException {
 130  0
     HttpSession session = melati.getSession();
 131  0
     ShoppingTrolley instance = (ShoppingTrolley) session.getAttribute(name());
 132  0
     if (instance == null || instance.isPaid()) {
 133  0
       instance = newTrolley(config);
 134  0
       instance.initialise(melati,config);
 135  0
       session.setAttribute(name(),instance);
 136  
     }
 137  0
     instance.configureRequest(melati);
 138  0
     return instance;
 139  
   }
 140  
 
 141  
   private boolean isPaid() {
 142  0
     return false;
 143  
   }
 144  
 
 145  
   public static synchronized ShoppingTrolley newTrolley(MelatiShoppingConfig config)
 146  
    throws InstantiationPropertyException {
 147  0
     return config.getShoppingTrolley();
 148  
   }
 149  
 
 150  
   /* get the Locale for this trolley
 151  
   */
 152  
   public abstract Locale getLocale();
 153  
 
 154  
 
 155  
   /* set the Locale for this trolley
 156  
   */
 157  
   public void setLocale(Locale locale){
 158  0
     this.locale = locale;
 159  0
   }
 160  
 
 161  
   /* confirm payment of this trolley
 162  
   */
 163  
   public abstract void confirmPayment(Melati melati);
 164  
 
 165  
   /* load a trolley from something persistent
 166  
   */
 167  
   public abstract void load(Integer id) throws InstantiationPropertyException;
 168  
 
 169  
   /* save a trolley to something persistent
 170  
   */
 171  
   public abstract void save();
 172  
 
 173  
   /* this is done for each request, so anything special that needs to be done
 174  
    * can be put in here
 175  
   */
 176  
   public void configureRequest(Melati melati) {
 177  0
     this.melati = melati;
 178  0
   }
 179  
 
 180  
   /* do something to force users to login
 181  
    * you could perhaps throw an access poem exception in order to let the
 182  
    * servlet generate the login page
 183  
    */
 184  
   public void assertLogin(Melati melati) {
 185  0
     JammyjoesDatabase db = (JammyjoesDatabase) melati.getDatabase();
 186  0
     Capability operator = db.getOperatorCapability();
 187  0
     AccessToken token = PoemThread.accessToken();
 188  0
     if (!token.givesCapability(operator))
 189  0
       throw new AccessPoemException(token, operator);
 190  0
   }
 191  
 
 192  
   /* set the user's detault details into this trolley.  this is useful
 193  
    * if users have already logged in, and we don't want them to reenter their
 194  
    * details
 195  
    */
 196  
   public abstract void setDefaultDetails(Melati melati);
 197  
 
 198  
 
 199  
   /* return the name of the trolley (for storing in the session
 200  
   */
 201  
   public static String name() {
 202  0
     return TROLLEY;
 203  
   }
 204  
 
 205  
   /* get the items from the trolley
 206  
   */
 207  
   public Enumeration getItems() {
 208  0
     return orderedItems.elements();
 209  
   }
 210  
 
 211  
   /* have we got anything in the trolley
 212  
   */
 213  
   public boolean isEmpty() {
 214  0
     return items.isEmpty();
 215  
   }
 216  
 
 217  
   /* have we entered any personal information
 218  
   */
 219  
   public boolean hasDetails() {
 220  0
     return hasDetails;
 221  
   }
 222  
 
 223  
   /* get an item from the trolley
 224  
   */
 225  
   public ShoppingTrolleyItem getItem(Integer id) {
 226  0
     return (ShoppingTrolleyItem)items.get(id);
 227  
   }
 228  
 
 229  
   /* remove an item from the trolley
 230  
   */
 231  
   public void removeItem(ShoppingTrolleyItem item) {
 232  0
     items.remove(item.getId());
 233  0
     orderedItems.removeElement(item);
 234  0
   }
 235  
 
 236  
   /* add an item to the trolley
 237  
   */
 238  
   public void addItem(ShoppingTrolleyItem item) {
 239  
     // don't add it if it's already there
 240  0
     if (!items.containsKey(item.getId())) {
 241  0
       orderedItems.add(item);
 242  
     }
 243  0
     items.put(item.getId(),item);
 244  0
   }
 245  
 
 246  
   public ShoppingTrolleyItem newItem(Integer id, String description, Double price)
 247  
    throws InstantiationPropertyException {
 248  0
     ShoppingTrolleyItem item = ShoppingTrolleyItem.newTrolleyItem(config);
 249  0
     item.initialise(this, melati, id, description, price);
 250  0
     addItem(item);
 251  0
     return item;
 252  
   }
 253  
 
 254  
   /* calculate the value of the items in the trolley
 255  
   */
 256  
   public double getValue() {
 257  0
     double value = 0;
 258  0
     for (Enumeration en = items.elements(); en.hasMoreElements();) {
 259  0
       ShoppingTrolleyItem product = (ShoppingTrolleyItem) en.nextElement();
 260  0
       value += product.getValue();
 261  0
     }
 262  0
     return value;
 263  
   }
 264  
 
 265  
   /* format the order value for display
 266  
      this value does not include discount or delivery, but does invlude VAT
 267  
   */
 268  
   public String getValueDisplay() {
 269  0
     return displayCurrency(getValue());
 270  
   }
 271  
 
 272  
   /* calculate the total value of this order
 273  
   */
 274  
   public double getTotalValue() {
 275  0
     return getValue() + getTotalDeliveryValue() + getDiscountValue() + getVATValue();
 276  
   }
 277  
 
 278  
   /* format the total order value for display
 279  
      this value includes discount, delivery and VAT
 280  
   */
 281  
   public String getTotalValueDisplay() {
 282  0
     return displayCurrency(getTotalValue());
 283  
   }
 284  
 
 285  
   /* format the total order value in pence, typically ecomerce sites
 286  
      accept the values in pence not pounds
 287  
   */
 288  
 
 289  
   public String getTotalValuePence() {
 290  0
     return getValuePence(getTotalValue());
 291  
   }
 292  
 
 293  
   public static String getValuePence(double totalValue) {
 294  0
     return (new Double(roundTo2dp(totalValue * 100))).intValue() + "";
 295  
   }
 296  
 
 297  
   /* provide a mechanism for working out if
 298  
      this order should include a delivery charge
 299  
   */
 300  
   public abstract boolean hasDelivery();
 301  
 
 302  
   /* you need to provide some mechanism for calculating the delivery
 303  
      value for the order (item delivery values are calculated individually
 304  
   */
 305  
   public abstract double getDeliveryValue();
 306  
 
 307  
   /* the delivery charge for the order is the sum of the charges on the items
 308  
      and an overall charge
 309  
   */
 310  
   public double getTotalDeliveryValue() {
 311  0
     double value = 0;
 312  0
     if (hasDelivery()) {
 313  0
       value = getDeliveryValue();
 314  0
       for (Enumeration en = items.elements(); en.hasMoreElements();) {
 315  0
         ShoppingTrolleyItem item = (ShoppingTrolleyItem) en.nextElement();
 316  0
         value += item.getDeliveryValue();
 317  0
       }
 318  
     }
 319  0
     return value;
 320  
   }
 321  
 
 322  
   /* format the devliery value for display
 323  
   */
 324  
   public String getDeliveryDisplay() {
 325  0
     return displayCurrency(getTotalDeliveryValue());
 326  
   }
 327  
 
 328  
   /* provide a mechanism for working out if
 329  
      this order should include a discount
 330  
   */
 331  
   public abstract boolean hasDiscount();
 332  
 
 333  
   /* if you want to apply a discount to this order, do it here
 334  
   */
 335  
   public abstract double getDiscountRate();
 336  
 
 337  
   /* work out the value of the discout applied to this order
 338  
      (returns a negative value)
 339  
   */
 340  
   public double getDiscountValue() {
 341  0
     double value = 0;
 342  0
     if (hasDiscount()) {
 343  0
       value = 0 - roundTo2dp(getValue()*getDiscountRate());
 344  
     }
 345  0
     return value;
 346  
   }
 347  
 
 348  
   /* display the discount (if present)
 349  
   */
 350  
   public String getDiscountRateDisplay() {
 351  0
     if (hasDiscount()) {
 352  
       try {
 353  0
         return (new Double(getDiscountRate())).intValue() + "%";
 354  0
       } catch (NumberFormatException e) {
 355  0
         return getDiscountRate() + "%";
 356  
       }
 357  
     } else {
 358  0
       return "";
 359  
     }
 360  
   }
 361  
 
 362  
   /* format the discount value for display
 363  
   */
 364  
   public String getDiscountValueDisplay() throws Exception {
 365  0
     return displayCurrency(getDiscountValue());
 366  
   }
 367  
 
 368  
   /* provide a mechanism for working out if
 369  
      this order should include VAT (default should be true)
 370  
   */
 371  
   public abstract boolean hasVAT();
 372  
 
 373  
   /* calculate the VAT value of the order
 374  
      typically items are priced inclusive of VAT and orders
 375  
      are therefor also inclusive of VAT.  If this order is
 376  
      for someone who should not be charged VAT, we need to subtract VAT
 377  
      from the order value
 378  
   */
 379  
   public double getVATValue() {
 380  0
     if (!hasVAT()) {
 381  0
       return roundTo2dp(getValue() * -0.14894);
 382  
     } else {
 383  0
       return 0;
 384  
     }
 385  
   }
 386  
 
 387  
   /* format the vat value for display
 388  
   */
 389  
   public String getVATDisplay() {
 390  0
     return displayCurrency(getVATValue());
 391  
   }
 392  
 
 393  
   /* set the address
 394  
   */
 395  
   public void setDeliveryAddress(String a) {
 396  0
     address = a;
 397  0
   }
 398  
   /* get the address
 399  
   */
 400  
   public String getDeliveryAddress() {
 401  0
     return address;
 402  
   }
 403  
 
 404  
   /* set the name
 405  
   */
 406  
   public void setName(String a) {
 407  0
     name = a;
 408  0
   }
 409  
   /* get the name
 410  
   */
 411  
   public String getName() {
 412  0
     return name;
 413  
   }
 414  
 
 415  
   /* set the email address
 416  
   */
 417  
   public void setEmail(String a) {
 418  0
     email = a;
 419  0
   }
 420  
   /* get the email address
 421  
   */
 422  
   public String getEmail() {
 423  0
     return email;
 424  
   }
 425  
 
 426  
   /* set the postcode
 427  
   */
 428  
   public void setPostcode(String a) {
 429  0
     postcode = a;
 430  0
   }
 431  
   /* get the postcode
 432  
   */
 433  
   public String getPostcode() {
 434  0
     return postcode;
 435  
   }
 436  
 
 437  
   /* set the telephone number
 438  
   */
 439  
   public void setTel(String a) {
 440  0
     tel = a;
 441  0
   }
 442  
   /* get the telephone number
 443  
   */
 444  
   public String getTel() {
 445  0
     return tel;
 446  
   }
 447  
 
 448  
   /* set the town
 449  
   */
 450  
   public void setTown(String a) {
 451  0
     town = a;
 452  0
   }
 453  
   /* get the town
 454  
   */
 455  
   public String getTown() {
 456  0
     return town;
 457  
   }
 458  
 
 459  
   /* set the county
 460  
   */
 461  
   public void setCounty(String a) {
 462  0
     county = a;
 463  0
   }
 464  
   /* get the county
 465  
   */
 466  
   public String getCounty() {
 467  0
     return county;
 468  
   }
 469  
 
 470  
   /* set the country
 471  
   */
 472  
   public void setCountry(String a) {
 473  0
     country = a;
 474  0
   }
 475  
   /* get the country
 476  
   */
 477  
   public String getCountry() {
 478  0
     return country;
 479  
   }
 480  
 
 481  
   /* set the delivery message
 482  
   */
 483  
   public void setMessage(String a) {
 484  0
     message = a;
 485  0
   }
 486  
   /* get the delivery message
 487  
   */
 488  
   public String getMessage() {
 489  0
     return message;
 490  
   }
 491  
 
 492  
   /* format a number in the locale currency
 493  
   */
 494  
   public String displayCurrency(double value) {
 495  0
     return new String(NumberFormat.getCurrencyInstance(getLocale()).format(value));
 496  
   }
 497  
 
 498  
   /* format a number in the locale currency
 499  
   */
 500  
   public String displayCurrency(Double value) {
 501  0
     return displayCurrency(value.doubleValue());
 502  
   }
 503  
 
 504  
   public String baseURL() {
 505  0
     String result = "";
 506  0
     if (JammyJoesUtil.telesales(melati)) {
 507  0
       result = "/telesales/";
 508  
     } else {
 509  0
       result = "/jammyjoes/";
 510  
     }
 511  0
     result += "Trolley/" + melati.getPoemContext().getLogicalDatabase() + "/";
 512  0
     return result;
 513  
   }
 514  
 
 515  
   public String viewURL() {
 516  0
     return baseURL() + "View/";
 517  
   }
 518  
 
 519  
   public String detailsURL() {
 520  0
     return baseURL() + "Details/";
 521  
   }
 522  
 
 523  
   public String confirmURL() {
 524  0
     return baseURL() + "Confirm/";
 525  
   }
 526  
 
 527  
   public String abandonURL() {
 528  0
     return baseURL() + "Abandon/";
 529  
   }
 530  
 
 531  
   public String updateURL() {
 532  0
     return baseURL() + "Update/";
 533  
   }
 534  
 
 535  
   public String paidURL() {
 536  0
     return baseURL() + "Paid/";
 537  
   }
 538  
 
 539  
   public String catalogueURL() {
 540  0
     return baseURL() + "CatalogueEntry/";
 541  
   }
 542  
 
 543  
   public static double roundTo2dp(double num) {
 544  0
     int a = Math.round(new Float(num * 100).floatValue());
 545  0
     double b = new Double(a).doubleValue();
 546  0
     return (b/100);
 547  
   }
 548  
 
 549  
 }
 550