Coverage Report - org.paneris.melati.shopping.ShoppingTrolley
 
Classes in this File Line Coverage Branch Coverage Complexity
ShoppingTrolley
0%
0/129
0%
0/16
1.179
 
 1  
 /*
 2  
  * $Source: /usr/cvsroot/MelatiShopping/src/main/java/org/paneris/melati/shopping/ShoppingTrolley.java,v $
 3  
  * $Revision: 1.25 $
 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 if you would like 
 30  
  * 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/~timj/
 43  
  *     68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
 44  
  */
 45  
 
 46  
 package org.paneris.melati.shopping;
 47  
 
 48  
 import java.util.Hashtable;
 49  
 import java.util.Vector;
 50  
 import java.util.Enumeration;
 51  
 import org.melati.Melati;
 52  
 import org.melati.servlet.Form;
 53  
 import org.melati.template.ServletTemplateContext;
 54  
 import javax.servlet.http.HttpSession;
 55  
 import java.text.NumberFormat;
 56  
 import java.util.Locale;
 57  
 import org.melati.util.InstantiationPropertyException;
 58  
 
 59  
  /**
 60  
  * <p> A Shopping Trolley stores information in the user's 
 61  
  * Shopping Trolley.</p>
 62  
  * <p> It does this by storing itself in the session.</p>
 63  
  * <p> For this reason, the constructors are private, and you will be expected
 64  
  * always to get the Shopping Trolley using getInstance();</p>
 65  
  * <p>
 66  
  * Usage example:
 67  
  * </p><p>
 68  
  * ShoppingTrolley trolley = ShoppingTrolley.getInstance(Melati melati);
 69  
  * context.put("trolley", trolley);
 70  
  * </p>
 71  
  **/
 72  
 
 73  0
 public abstract class ShoppingTrolley {
 74  
 
 75  0
   private static String TROLLEY = 
 76  
       "org.paneris.melati.shopping.DefaultShoppingTrolley";
 77  
   protected Locale locale;
 78  
   protected String address;
 79  
   protected String name;
 80  
   protected String tel;
 81  
   protected String town;
 82  
   protected String county;
 83  
   protected String country;
 84  
   protected String postcode;
 85  
   protected String message;
 86  
   protected String email;
 87  0
   protected boolean hasDetails = false;
 88  0
   Vector orderedItems = new Vector();
 89  0
   Hashtable items = new Hashtable();
 90  
 
 91  
   public static final double VAT_PERCENT_TIMES_TEN = 175.0;
 92  
   public MelatiShoppingConfig config;
 93  
   public Melati melati;
 94  
 
 95  
  /**
 96  
   * Private Constructor to build an empty ShoppingTrolley
 97  
   **/
 98  
   protected void initialise(Melati melatiIn, MelatiShoppingConfig configIn) {
 99  0
     this.config = configIn;
 100  0
     this.melati = melatiIn;
 101  0
   }
 102  
 
 103  
   /**
 104  
    * Public Constructor to build a trolley from some id.
 105  
    */
 106  
   public void initialise(Melati melatiIn, 
 107  
                          MelatiShoppingConfig configIn, Integer id)
 108  
    throws InstantiationPropertyException {
 109  0
     initialise(melatiIn,configIn);
 110  0
     load(id);
 111  0
     HttpSession session = melati.getSession();
 112  0
     session.setAttribute(name(),this);
 113  0
   }
 114  
 
 115  
   /**
 116  
    * Remove any trolley from the session.
 117  
    */
 118  
   public void remove(Melati melatiIn) {
 119  0
     HttpSession session = melatiIn.getSession();
 120  0
     session.removeAttribute(name());
 121  0
   }
 122  
 
 123  
 
 124  
   /**
 125  
    * Returns the single instance, creating one if it can't be found.
 126  
    */
 127  
   public static synchronized ShoppingTrolley 
 128  
       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) {
 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  
   public static synchronized ShoppingTrolley 
 142  
       newTrolley(MelatiShoppingConfig config)
 143  
       throws InstantiationPropertyException {
 144  0
     return config.getShoppingTrolley();
 145  
   }
 146  
 
 147  
  /**
 148  
   * Get the Locale for this trolley.
 149  
   */
 150  
   public abstract Locale getLocale();
 151  
 
 152  
 
 153  
  /**
 154  
   * Set the Locale for this trolley.
 155  
   */
 156  
   public void setLocale(Locale locale){
 157  0
     this.locale = locale;
 158  0
   }
 159  
 
 160  
  /**
 161  
   * Confirm payment of this trolley.
 162  
   */
 163  
   public abstract void confirmPayment(Melati melatiIn);
 164  
 
 165  
  /**
 166  
   * Load a trolley from something persistent.
 167  
   */
 168  
   public abstract void load(Integer id) throws InstantiationPropertyException;
 169  
 
 170  
  /**
 171  
   * Save a trolley to something persistent.
 172  
   */
 173  
   public abstract void save();
 174  
 
 175  
  /**
 176  
   * This is done for each request, so anything special that needs to be done
 177  
   * can be put in here
 178  
   */
 179  
   public void configureRequest(Melati melatiIn) {
 180  0
     this.melati = melatiIn;
 181  0
   }
 182  
 
 183  
   /**
 184  
    *  Do something to force users to login.
 185  
    * You could perhaps throw an access poem exception in order to let the
 186  
    * servlet generate the login page.
 187  
    */
 188  
   public abstract void assertLogin(Melati melatiIn);
 189  
 
 190  
   /**
 191  
    * Set the user's detault details into this trolley.  
 192  
    * This is useful if users have already logged in, 
 193  
    * and we don't want them to reenter their details.
 194  
    */
 195  
   public abstract void setDefaultDetails(Melati melatiIn);
 196  
 
 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  
  /**
 206  
   * Get the items from the trolley.
 207  
   */
 208  
   public Enumeration getItems() {
 209  0
     return orderedItems.elements();
 210  
   }
 211  
 
 212  
  /**
 213  
   * Have we got anything in the trolley.
 214  
   */
 215  
   public boolean isEmpty() {
 216  0
     return items.isEmpty();
 217  
   }
 218  
 
 219  
  /**
 220  
   * Have we entered any personal information.
 221  
   */
 222  
   public boolean hasDetails() {
 223  0
     return hasDetails;
 224  
   }
 225  
 
 226  
  /**
 227  
   * Get an item from the trolley.
 228  
   */
 229  
   public ShoppingTrolleyItem getItem(Integer id) {
 230  0
     return (ShoppingTrolleyItem)items.get(id);
 231  
   }
 232  
 
 233  
  /**
 234  
   * Remove an item from the trolley.
 235  
   */
 236  
   public void removeItem(ShoppingTrolleyItem item) {
 237  0
     items.remove(item.getId());
 238  0
     orderedItems.removeElement(item);
 239  0
   }
 240  
 
 241  
  /**
 242  
   * Add an item to the trolley.
 243  
   */
 244  
   public void addItem(ShoppingTrolleyItem item) {
 245  
     // don't add it if it's already there
 246  0
     if (!items.containsKey(item.getId())) {
 247  0
       orderedItems.add(item);
 248  
     }
 249  0
     items.put(item.getId(),item);
 250  0
   }
 251  
 
 252  
  /**
 253  
   * Create an item and put it in the Trolley.
 254  
   * 
 255  
   * @param id
 256  
   * @param description
 257  
   * @param price
 258  
   * @return a newly created item in the Trolley
 259  
   * @throws InstantiationPropertyException
 260  
   */
 261  
   public ShoppingTrolleyItem newItem(Integer id, String description, 
 262  
                                      Double price)
 263  
    throws InstantiationPropertyException {
 264  0
     ShoppingTrolleyItem item = ShoppingTrolleyItem.newTrolleyItem(config);
 265  0
     item.initialise(this, melati, id, description, price);
 266  0
     addItem(item);
 267  0
     return item;
 268  
   }
 269  
 
 270  
  /**
 271  
   * Calculate the value of the items in the trolley.
 272  
   */
 273  
   public double getValue() {
 274  0
     double value = 0;
 275  0
     for (Enumeration en = items.elements(); en.hasMoreElements();) {
 276  0
       ShoppingTrolleyItem product = (ShoppingTrolleyItem) en.nextElement();
 277  0
       value += product.getValue();
 278  0
     }
 279  0
     return value;
 280  
   }
 281  
 
 282  
  /**
 283  
   * Format the order value for display.
 284  
   * This value does not include discount or delivery, but does invlude VAT.
 285  
   */
 286  
   public String getValueDisplay() {
 287  0
     return displayCurrency(getValue());
 288  
   }
 289  
 
 290  
  /**
 291  
   * Calculate the total value of this order.
 292  
   */
 293  
   public double getTotalValue() {
 294  0
     return getValue() + 
 295  
            getTotalDeliveryValue() + 
 296  
            getDiscountValue() + 
 297  
            getVATValue();
 298  
   }
 299  
 
 300  
  /**
 301  
   * Format the total order value for display.
 302  
   * This value includes discount, delivery and VAT.
 303  
   */
 304  
   public String getTotalValueDisplay() {
 305  0
     return displayCurrency(getTotalValue());
 306  
   }
 307  
 
 308  
  /**
 309  
   * Format the total order value in pence, typically ecomerce sites
 310  
   * accept the values in pence not pounds.
 311  
   */
 312  
   public String getTotalValuePence() {
 313  0
     return (new Double(roundTo2dp(getTotalValue() * 100))).intValue() + "";
 314  
   }
 315  
 
 316  
  /**
 317  
   * Provide a mechanism for working out if
 318  
   * this order should include a delivery charge.
 319  
   */
 320  
   public abstract boolean hasDelivery();
 321  
 
 322  
  /**
 323  
   * You need to provide some mechanism for calculating the delivery
 324  
   * value for the order (item delivery values are calculated individually.
 325  
   */
 326  
   public abstract double getDeliveryValue();
 327  
 
 328  
  /**
 329  
   * The delivery charge for the order is the sum of the charges on the items
 330  
   * and an overall charge.
 331  
   */
 332  
   public double getTotalDeliveryValue() {
 333  0
     double value = 0;
 334  0
     if (hasDelivery()) {
 335  0
       value = getDeliveryValue();
 336  0
       for (Enumeration en = items.elements(); en.hasMoreElements();) {
 337  0
         ShoppingTrolleyItem item = (ShoppingTrolleyItem)en.nextElement();
 338  0
         value += item.getDeliveryValue();
 339  0
       }
 340  
     }
 341  0
     return value;
 342  
   }
 343  
 
 344  
  /**
 345  
   * Format the delivery value for display.
 346  
   */
 347  
   public String getDeliveryDisplay() {
 348  0
     return displayCurrency(getTotalDeliveryValue());
 349  
   }
 350  
 
 351  
  /**
 352  
   * Provide a mechanism for working out if
 353  
   * this order should include a discount.
 354  
   */
 355  
   public abstract boolean hasDiscount();
 356  
 
 357  
  /**
 358  
   * If you want to apply a discount to this order, do it here.
 359  
   */
 360  
   public abstract double getDiscountRate();
 361  
 
 362  
  /**
 363  
   * Work out the value of the discout applied to this order
 364  
   * (returns a negative value).
 365  
   */
 366  
   public double getDiscountValue() {
 367  0
     double value = 0;
 368  0
     if (hasDiscount()) {
 369  0
       value = 0 - roundTo2dp(getValue()*getDiscountRate());
 370  
     }
 371  0
     return value;
 372  
   }
 373  
 
 374  
  /**
 375  
   * Display the discount (if present).
 376  
   */
 377  
   public String getDiscountRateDisplay() {
 378  0
     if (hasDiscount()) {
 379  
       try {
 380  0
         return (new Double(getDiscountRate())).intValue() + "%";
 381  0
       } catch (NumberFormatException e) {
 382  0
         return getDiscountRate() + "%";
 383  
       }
 384  
     } else {
 385  0
       return "";
 386  
     }
 387  
   }
 388  
 
 389  
  /**
 390  
   * Format the discount value for display.
 391  
   */
 392  
   public String getDiscountValueDisplay() throws Exception {
 393  0
     return displayCurrency(getDiscountValue());
 394  
   }
 395  
 
 396  
  /**
 397  
   * Provide a mechanism for working out if
 398  
   * this order should include VAT (default should be true).
 399  
   */
 400  
   public abstract boolean hasVAT();
 401  
 
 402  
  /**
 403  
   * Calculate the VAT value of the order.
 404  
   * Typically items are priced inclusive of VAT and orders
 405  
   * are therefore also inclusive of VAT.  If this order is
 406  
   * for someone who should not be charged VAT, we need to subtract VAT
 407  
   * from the order value.
 408  
   */
 409  
   public double getVATValue() {
 410  0
     if (!hasVAT()) {
 411  0
       return roundTo2dp((getValue() * 
 412  
                         (-1 * (1.0 - (1000.0/VAT_PERCENT_TIMES_TEN)))));
 413  
     } else {
 414  0
       return 0;
 415  
     }
 416  
   }
 417  
 
 418  
  /**
 419  
   * Format the vat value for display.
 420  
   */
 421  
   public String getVATDisplay() {
 422  0
     return displayCurrency(getVATValue());
 423  
   }
 424  
 
 425  
  /**
 426  
   * Set values from form fileds. 
 427  
   * @param melati
 428  
   */
 429  
   public void setFromForm(Melati melati) {
 430  0
     ServletTemplateContext tc = melati.getServletTemplateContext();
 431  0
     setName(Form.getFormNulled(tc,"trolley_name"));
 432  0
     setEmail(Form.getFormNulled(tc,"trolley_email"));
 433  0
     setTel(Form.getFormNulled(tc,"trolley_tel"));
 434  0
     setDeliveryAddress(Form.getFormNulled(tc,"trolley_deliveryaddress"));
 435  0
     setTown(Form.getFormNulled(tc,"trolley_town"));
 436  0
     setCounty(Form.getFormNulled(tc,"trolley_county"));
 437  0
     setCountry(Form.getFormNulled(tc,"trolley_country"));
 438  0
     setPostcode(Form.getFormNulled(tc,"trolley_postcode"));
 439  0
     setMessage(Form.getFormNulled(tc,"trolley_message"));
 440  0
     hasDetails = true;
 441  0
   }
 442  
 
 443  
  /**
 444  
   * Set the address.
 445  
   */
 446  
   public void setDeliveryAddress(String a) {
 447  0
     address = a;
 448  0
   }
 449  
  /**
 450  
   * Get the address.
 451  
   */
 452  
   public String getDeliveryAddress() {
 453  0
     return address;
 454  
   }
 455  
 
 456  
  /**
 457  
   * Set the name.
 458  
   */
 459  
   public void setName(String a) {
 460  0
     name = a;
 461  0
   }
 462  
  /**
 463  
   * Get the name.
 464  
   */
 465  
   public String getName() {
 466  0
     return name;
 467  
   }
 468  
 
 469  
  /**
 470  
   * Set the email address.
 471  
   */
 472  
   public void setEmail(String a) {
 473  0
     email = a;
 474  0
   }
 475  
  /**
 476  
   * Get the email address.
 477  
   */
 478  
   public String getEmail() {
 479  0
     return email;
 480  
   }
 481  
 
 482  
  /**
 483  
   * Set the postcode.
 484  
   */
 485  
   public void setPostcode(String a) {
 486  0
     postcode = a;
 487  0
   }
 488  
  /**
 489  
   * Get the postcode.
 490  
   */
 491  
   public String getPostcode() {
 492  0
     return postcode;
 493  
   }
 494  
 
 495  
  /**
 496  
   * Set the telephone number.
 497  
   */
 498  
   public void setTel(String a) {
 499  0
     tel = a;
 500  0
   }
 501  
  /**
 502  
   * Get the telephone number.
 503  
   */
 504  
   public String getTel() {
 505  0
     return tel;
 506  
   }
 507  
 
 508  
  /**
 509  
   * Set the town.
 510  
   */
 511  
   public void setTown(String a) {
 512  0
     town = a;
 513  0
   }
 514  
  /**
 515  
   * Get the town.
 516  
   */
 517  
   public String getTown() {
 518  0
     return town;
 519  
   }
 520  
 
 521  
  /**
 522  
   * Set the county.
 523  
   */
 524  
   public void setCounty(String a) {
 525  0
     county = a;
 526  0
   }
 527  
  /**
 528  
   * Get the county.
 529  
   */
 530  
   public String getCounty() {
 531  0
     return county;
 532  
   }
 533  
 
 534  
  /**
 535  
   * Set the country.
 536  
   */
 537  
   public void setCountry(String a) {
 538  0
     country = a;
 539  0
   }
 540  
  /**
 541  
   * Get the country.
 542  
   */
 543  
   public String getCountry() {
 544  0
     return country;
 545  
   }
 546  
 
 547  
  /**
 548  
   * Set the delivery message.
 549  
   */
 550  
   public void setMessage(String a) {
 551  0
     message = a;
 552  0
   }
 553  
  /**
 554  
   * Get the delivery message.
 555  
   */
 556  
   public String getMessage() {
 557  0
     return message;
 558  
   }
 559  
 
 560  
  /**
 561  
   * Format a number in the locale currency.
 562  
   */
 563  
   public String displayCurrency(double value) {
 564  0
     return new String(NumberFormat.getCurrencyInstance(
 565  
                                        getLocale()).format(value));
 566  
   }
 567  
 
 568  
  /**
 569  
   * Format a number in the locale currency.
 570  
   */
 571  
   public String displayCurrency(Double value) {
 572  0
     return displayCurrency(value.doubleValue());
 573  
   }
 574  
 
 575  
   public String baseURL() {
 576  0
     return melati.getRequest().getServletPath() + "/" +
 577  
            melati.getPoemContext().getLogicalDatabase() + "/";
 578  
   }
 579  
 
 580  
   public String viewURL() {
 581  0
     return baseURL() + "View/";
 582  
   }
 583  
 
 584  
   public String detailsURL() {
 585  0
     return baseURL() + "Details/";
 586  
   }
 587  
 
 588  
   public String confirmURL() {
 589  0
     return baseURL() + "Confirm/";
 590  
   }
 591  
 
 592  
   public String abandonURL() {
 593  0
     return baseURL() + "Abandon/";
 594  
   }
 595  
 
 596  
   public String updateURL() {
 597  0
     return baseURL() + "Update/";
 598  
   }
 599  
 
 600  
   public String paidURL() {
 601  0
     return baseURL() + "Paid/";
 602  
   }
 603  
 
 604  
   public static double roundTo2dp(double num) {
 605  0
     int a = Math.round(new Float(num * 100).floatValue());
 606  0
     double b = new Double(a).doubleValue();
 607  0
     return (b/100);
 608  
   }
 609  
 
 610  
 }
 611