An applet that permits freehand drawing

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/** An applet that lets you perform freehand drawing.
 *  


 ****************

public class SimpleWhiteboard extends Applet {
  protected int lastX=0, lastY=0;

  public void init() {
    setBackground(Color.white);
    setForeground(Color.blue);
    addMouseListener(new PositionRecorder());
    addMouseMotionListener(new LineDrawer());
  }

  protected void record(int x, int y) {
    lastX = x;
    lastY = y;
  }

  // Record position that mouse entered window or
  // where user pressed mouse button.
  
  private class PositionRecorder extends MouseAdapter {
    public void mouseEntered(MouseEvent event) {
      requestFocus(); // Plan ahead for typing
      record(event.getX(), event.getY());
    }

    public void mousePressed(MouseEvent event) {
      record(event.getX(), event.getY());
    }
  }

  // As user drags mouse, connect subsequent positions
  // with short line segments.
  
  private class LineDrawer extends MouseMotionAdapter {
    public void mouseDragged(MouseEvent event) {
      int x = event.getX();
      int y = event.getY();
      Graphics g = getGraphics();
      g.drawLine(lastX, lastY, x, y);
      record(x, y);
    }
  }
}

A TextField that uses key events to correct the spelling of the names of computer languages entered into it

import java.awt.*;
import java.awt.event.*;

/** A spelling-correcting TextField for entering
 *  a language name.
 *  


 *******************

public class LanguageField extends TextField {
  private String[] substrings =
    { "", "J", "Ja", "Jav", "Java" };

  public LanguageField() {
    addKeyListener(new SpellingCorrector());
    addActionListener(new WordCompleter());
    addFocusListener(new SubliminalAdvertiser());
  }

  // Put caret at end of field.
  
  private void setCaret() {
    setCaretPosition(5);
  }
  
  // Listener to monitor/correct spelling as user types.
  
  private class SpellingCorrector extends KeyAdapter {
    public void keyTyped(KeyEvent event) {
      setLanguage();
      setCaret();
    }

    // Enter partial name of good programming language that
    // most closely matches what they've typed so far.
    
    private void setLanguage() {
      int length = getText().length();
      if (length <= 4) {
        setText(substrings[length]);
      } else {
        setText("Java");
      }
      setCaret();
    }
  }

  // Listener to replace current partial name with
  // most closely-matching name of good language.
  
  private class WordCompleter implements ActionListener {

    // When they hit RETURN, fill in the right answer.
    
    public void actionPerformed(ActionEvent event) {
      setText("Java");
      setCaret();
    }
  }

  // Listener to give the user a hint.
  
  private class SubliminalAdvertiser extends FocusAdapter {
    public void focusGained(FocusEvent event) {
      String text = getText();
      for(int i=0; i<10; i++) {
        setText("Hint: Java");
        setText(text);
      }
    }
  }
}

DebugTag.java Custom tag that optionally makes use of a tag body

DebugTag.java Custom tag that optionally makes use of a tag body

package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import javax.servlet.*;

/** A tag that includes the body content only if
 *  the "debug" request parameter is set.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class DebugTag extends TagSupport {
  public int doStartTag() {
    ServletRequest request = pageContext.getRequest();
    String debugFlag = request.getParameter("debug");
    if ((debugFlag != null) &&
        (!debugFlag.equalsIgnoreCase("false"))) {
      return(EVAL_BODY_INCLUDE);
    } else {
      return(SKIP_BODY);
    }
  }
}

HeadingTag.java Custom tag that makes use of a tag body

HeadingTag.java Custom tag that makes use of a tag body


package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

/** Generates an HTML heading with the specified background
 *  color, foreground color, alignment, font, and font size.
 *  You can also turn on a border around it, which normally
 *  just barely encloses the heading, but which can also
 *  stretch wider. All attributes except the background
 *  color are optional.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class HeadingTag extends TagSupport {
  private String bgColor; // The one required attribute
  private String color = null;
  private String align="CENTER";
  private String fontSize="36";
  private String fontList="Arial, Helvetica, sans-serif";
  private String border="0";
  private String width=null;

  public void setBgColor(String bgColor) {
    this.bgColor = bgColor;
  }

  public void setColor(String color) {
    this.color = color;
  }

  public void setAlign(String align) {
    this.align = align;
  }

  public void setFontSize(String fontSize) {
    this.fontSize = fontSize;
  }

  public void setFontList(String fontList) {
    this.fontList = fontList;
  }

  public void setBorder(String border) {
    this.border = border;
  }

  public void setWidth(String width) {
    this.width = width;
  }

  public int doStartTag() {
    try {
      JspWriter out = pageContext.getOut();
      out.print("<TABLE BORDER=" + border +
                " BGCOLOR=\"" + bgColor + "\"" +
                " ALIGN=\"" + align + "\"");
      if (width != null) {
        out.print(" WIDTH=\"" + width + "\"");
      }
      out.print("><TR><TH>");
      out.print("<SPAN STYLE=\"" +
                "font-size: " + fontSize + "px; " +
                "font-family: " + fontList + "; ");
      if (color != null) {
        out.println("color: " + color + ";");
      }
      out.print("\"> "); // End of <SPAN ...>
    } catch(IOException ioe) {
      System.out.println("Error in HeadingTag: " + ioe);
    }
    return(EVAL_BODY_INCLUDE); // Include tag body
  }

  public int doEndTag() {
    try {
      JspWriter out = pageContext.getOut();
      out.print("</SPAN></TABLE>");
    } catch(IOException ioe) {
      System.out.println("Error in HeadingTag: " + ioe);
    }
    return(EVAL_PAGE); // Continue with rest of JSP page
  }
}

PrimeTag.java Custom tag that outputs a random prime number of a user-specifiable approximate length

PrimeTag.java Custom tag that outputs a random prime number of a user-specifiable approximate length

package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;

/** Generates an N-digit random prime (default N = 50).
 *  Extends SimplePrimeTag, adding a length attribute
 *  to set the size of the prime. The doStartTag
 *  method of the parent class uses the len field
 *  to determine the approximate length of the prime.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class PrimeTag extends SimplePrimeTag {
  public void setLength(String length) {
    try {
      len = Integer.parseInt(length);
    } catch(NumberFormatException nfe) {
      len = 50;
    }
  }
}

SimplePrimeTag.java Custom tag that outputs a random prime number of a fixed approximate length

SimplePrimeTag.java Custom tag that outputs a random prime number of a fixed approximate length


package cwp.tags;

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
import java.math.*;
import cwp.*;

/** Generates a prime of approximately 50 digits.
 *  (50 is actually the length of the random number
 *  generated -- the first prime above that number will
 *  be returned.)
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class SimplePrimeTag extends TagSupport {
  protected int len = 50;

  public int doStartTag() {
    try {
      JspWriter out = pageContext.getOut();
      BigInteger prime = Primes.nextPrime(Primes.random(len));
      out.print(prime);
    } catch(IOException ioe) {
      System.out.println("Error generating prime: " + ioe);
    }
    return(SKIP_BODY);
  }
}

cwp-taglib.tld Tag Library Descriptor file used by the custom tags in this chapter.

cwp-taglib.tld Tag Library Descriptor file used by the custom tags in this chapter.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
 PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
 "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<!-- a tag library descriptor -->

<taglib>
  <!-- after this the default space is
        "http://java.sun.com/j2ee/dtds/jsptaglibrary_1_2.dtd"
   -->

  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>cwp</shortname>
  <!-- ** CHANGED FROM "urn" TO "uri" IN TOMCAT 3.1 final ** -->
  <uri></uri>
  <info>
    A tag library from Core Web Programming Java 2 Edition,
    .
  </info>

<!--
  <tag>
    The name (after prefix) tag will have in JSP code
    <name>example</name>

    The actual class implementing tag. In
    Tomcat 3.1, it MUST be in a package.
    <tagclass>cwp.tags.ExampleTag</tagclass>

    Descriptive information about tag.
    <info>Simplest example: inserts one line of output</info>

    One of three values describing what goes between
    start and end tag. 
      empty: no body 
      JSP: body that is evaluated by container normally,
           then possibly processed by tag
      tagdependent: body is only processed by tag;
                    JSP in body is not evaluated. 
    ** NOTE: TOMCAT 3.1 FINAL DOES NOT SUPPORT BODYCONTENT **
    ** THE BETA SUPPORTED IT, AND IT IS PART OF SPEC, BUT... **
    <bodycontent>empty</bodycontent>
  </tag>      
-->

  <tag>
    <name>example</name>
    <tagclass>cwp.tags.ExampleTag</tagclass>
    <info>Simplest example: inserts one line of output</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>empty</bodycontent> -->
  </tag>      

  <tag>
    <name>simplePrime</name>
    <tagclass>cwp.tags.SimplePrimeTag</tagclass>
    <info>Outputs a random 50-digit prime.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>empty</bodycontent> -->
  </tag>

  <tag>
    <name>prime</name>
    <tagclass>cwp.tags.PrimeTag</tagclass>
    <info>Outputs a random N-digit prime.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT
    <bodycontent>empty</bodycontent> -->
    <attribute>
      <name>length</name>
      <required>false</required>
    </attribute>
  </tag>

  <tag>
    <name>heading</name>
    <tagclass>cwp.tags.HeadingTag</tagclass>
    <info>Outputs a 1-cell table used as a heading.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
    <attribute>
      <name>bgColor</name>
      <required>true</required>  <!-- bgColor is required -->
    </attribute>
    <attribute>
      <name>color</name>
      <required>false</required>
    </attribute>
    <attribute>
      <name>align</name>
      <required>false</required>
    </attribute>
    <attribute>
      <name>fontSize</name>
      <required>false</required>
    </attribute>
    <attribute>
      <name>fontList</name>
      <required>false</required>
    </attribute>
    <attribute>
      <name>border</name>
      <required>false</required>
    </attribute>
    <attribute>
      <name>width</name>
      <required>false</required>
    </attribute>
  </tag>

  <tag>
    <name>debug</name>
    <tagclass>cwp.tags.DebugTag</tagclass>
    <info>Includes body only if debug param is set.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

  <tag>
    <name>filter</name>
    <tagclass>cwp.tags.FilterTag</tagclass>
    <info>Replaces HTML-specific characters in body.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

  <tag>
    <name>repeat</name>
    <tagclass>cwp.tags.RepeatTag</tagclass>
    <info>Repeats body the specified number of times.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
    <attribute>
      <name>reps</name>
      <required>true</required>
      <!-- rtexprvalue indicates whether attribute
           can be a JSP expression. -->
      <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>

  <tag>
    <name>if</name>
    <tagclass>cwp.tags.IfTag</tagclass>
    <info>if/condition/then/else tag.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

  <tag>
    <name>condition</name>
    <tagclass>cwp.tags.IfConditionTag</tagclass>
    <info>condition part of if/condition/then/else tag.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

  <tag>
    <name>then</name>
    <tagclass>cwp.tags.IfThenTag</tagclass>
    <info>then part of if/condition/then/else tag.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

  <tag>
    <name>else</name>
    <tagclass>cwp.tags.IfElseTag</tagclass>
    <info>else part of if/condition/then/else tag.</info>
    <!-- TOMCAT 3.1 DOES NOT SUPPORT BODYCONTENT 
    <bodycontent>JSP</bodycontent> -->
  </tag>

</taglib>

SharedCounts1.jsp, SharedCounts2.jsp, and SharedCounts3.jsp Three pages that all use the AccessCountBean. Results you get depend on which page is hit first and how many total hits the combined pages receive.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of sharing beans. 

Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Shared Access Counts: Page 1</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>

<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Shared Access Counts: Page 1</TABLE>
<P>
<jsp:useBean id="counter" 
             class="cwp.AccessCountBean"
             scope="application">
  <jsp:setProperty name="counter" 
                   property="firstPage"
                   value="SharedCounts1.jsp" />
</jsp:useBean>

Of SharedCounts1.jsp (this page), 
<A HREF="SharedCounts2.jsp">SharedCounts2.jsp</A>, and
<A HREF="SharedCounts3.jsp">SharedCounts3.jsp</A>, 
<jsp:getProperty name="counter" property="firstPage" />
was the first page accessed.
<P>
Collectively, the three pages have been accessed 
<jsp:getProperty name="counter" property="accessCount" />
times.
             
</BODY>
</HTML>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of sharing beans. 
   
Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Shared Access Counts: Page 2</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Shared Access Counts: Page 2</TABLE>
<P>
<jsp:useBean id="counter" 
             class="cwp.AccessCountBean"
             scope="application">
  <jsp:setProperty name="counter" 
                   property="firstPage"
                   value="SharedCounts2.jsp" />
</jsp:useBean>
Of SharedCounts2.jsp (this page), 
<A HREF="SharedCounts1.jsp">SharedCounts1.jsp</A>, and
<A HREF="SharedCounts3.jsp">SharedCounts3.jsp</A>, 
<jsp:getProperty name="counter" property="firstPage" />
was the first page accessed.
<P>
Collectively, the three pages have been accessed 
<jsp:getProperty name="counter" property="accessCount" />
times.      
</BODY>
</HTML>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of sharing beans. 

Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Shared Access Counts: Page 3</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Shared Access Counts: Page 3</TABLE>
<P>
<jsp:useBean id="counter" 
             class="cwp.AccessCountBean"
             scope="application">
  <jsp:setProperty name="counter" 
                   property="firstPage"
                   value="SharedCounts3.jsp" />
</jsp:useBean>
Of SharedCounts3.jsp (this page), 
<A HREF="SharedCounts1.jsp">SharedCounts1.jsp</A>, and
<A HREF="SharedCounts2.jsp">SharedCounts2.jsp</A>, 
<jsp:getProperty name="counter" property="firstPage" />
was the first page accessed.
<P>
Collectively, the three pages have been accessed 
<jsp:getProperty name="counter" property="accessCount" />
times.         
</BODY>
</HTML>

SaleEntry3.jsp Page that uses the SaleEntry bean, using property=”*” to read request parameters and assign them to bean properties

SaleEntry3.jsp Page that uses the SaleEntry bean, using property="*" to read request parameters and assign them to bean properties


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of using jsp:setProperty and a general association
with the input parameters. See SaleEntry1.jsp
and SaleEntry2.jsp for alternatives. 
   
Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Using jsp:setProperty</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Using jsp:setProperty</TABLE>
<jsp:useBean id="entry" class="cwp.SaleEntry" />
<%-- WARNING! Both the JSWDK 1.0.1 and the Java Web Server
              have a bug that makes them fail on automatic
              type conversions to double values.
--%>
<jsp:setProperty name="entry" property="*" />
<BR>
<TABLE ALIGN="CENTER" BORDER=1>
<TR CLASS="COLORED">
  <TH>Item ID<TH>Unit Price<TH>Number Ordered<TH>Total Price
<TR ALIGN="RIGHT">
  <TD><jsp:getProperty name="entry" property="itemID" />
  <TD>$<jsp:getProperty name="entry" property="itemCost" />
  <TD><jsp:getProperty name="entry" property="numItems" />
  <TD>$<jsp:getProperty name="entry" property="totalCost" />
</TABLE>      
</BODY>
</HTML>

SaleEntry.java //SaleEntry Bean
package cwp;

/** Simple bean to illustrate the various forms
 *  of jsp:setProperty.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class SaleEntry {
  private String itemID = "unknown";
  private double discountCode = 1.0;
  private int numItems = 0;

  public String getItemID() {
    return(itemID);
  }

  public void setItemID(String itemID) {
    if (itemID != null) {
      this.itemID = itemID;
    } else {
      this.itemID = "unknown";
    }
  }

  public double getDiscountCode() {
    return(discountCode);
  }

  public void setDiscountCode(double discountCode) {
    this.discountCode = discountCode;
  }

  public int getNumItems() {
    return(numItems);
  }

  public void setNumItems(int numItems) {
    this.numItems = numItems;
  }

  // In real life, replace this with database lookup.

  public double getItemCost() {
    double cost;
    if (itemID.equals("a1234")) {
      cost = 12.99*getDiscountCode();
    } else {
      cost = -9999;
    }
    return(roundToPennies(cost));
  }

  private double roundToPennies(double cost) {
    return(Math.floor(cost*100)/100.0);
  }

  public double getTotalCost() {
    return(getItemCost() * getNumItems());
  }
}

SaleEntry1.jsp Page that uses the SaleEntry bean, using explicit Java code to read request parameters and assign them to bean properties.

SaleEntry1.jsp Page that uses the SaleEntry bean, using explicit Java code to read request parameters and assign them to bean properties.

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- 
Example of using jsp:setProperty with an explicit value
supplied to the "value" attribute. See SaleEntry2.jsp
and SaleEntry3.jsp for alternatives. 

Taken from Core Web Programming Java 2 Edition
from Prentice Hall and Sun Microsystems Press,
.
May be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Using jsp:setProperty</TITLE>
<LINK REL=STYLESHEET
      HREF="JSP-Styles.css"
      TYPE="text/css">
</HEAD>

<BODY>
<TABLE BORDER=5 ALIGN="CENTER">
  <TR><TH CLASS="TITLE">
      Using jsp:setProperty</TABLE>
<jsp:useBean id="entry" class="cwp.SaleEntry" />
<jsp:setProperty 
    name="entry" 
    property="itemID"
    value='<%= request.getParameter("itemID") %>' />
<%
int numItemsOrdered = 1;
try {
  numItemsOrdered = 
    Integer.parseInt(request.getParameter("numItems"));
} catch(NumberFormatException nfe) {}
%>
<jsp:setProperty 
    name="entry" 
    property="numItems"
    value="<%= numItemsOrdered %>" />
<% 
double discountCode = 1.0;
try {
  String discountString = 
    request.getParameter("discountCode");
  // Double.parseDouble not available in JDK 1.1.
  discountCode = 
    Double.valueOf(discountString).doubleValue();
} catch(NumberFormatException nfe) {}
%>
<jsp:setProperty 
    name="entry" 
    property="discountCode"
    value="<%= discountCode %>" />
<BR>
<TABLE ALIGN="CENTER" BORDER=1>
<TR CLASS="COLORED">
  <TH>Item ID<TH>Unit Price<TH>Number Ordered<TH>Total Price
<TR ALIGN="RIGHT">
  <TD><jsp:getProperty name="entry" property="itemID" />
  <TD>$<jsp:getProperty name="entry" property="itemCost" />
  <TD><jsp:getProperty name="entry" property="numItems" />
  <TD>$<jsp:getProperty name="entry" property="totalCost" />
</TABLE>       
</BODY>
</HTML>


SaleEntry.Java //sale entry bean

package cwp;

/** Simple bean to illustrate the various forms
 *  of jsp:setProperty.
 *  <P>
 *  Taken from Core Web Programming Java 2 Edition
 *  from Prentice Hall and Sun Microsystems Press,
 *  .
 *  May be freely used or adapted.
 */

public class SaleEntry {
  private String itemID = "unknown";
  private double discountCode = 1.0;
  private int numItems = 0;

  public String getItemID() {
    return(itemID);
  }

  public void setItemID(String itemID) {
    if (itemID != null) {
      this.itemID = itemID;
    } else {
      this.itemID = "unknown";
    }
  }

  public double getDiscountCode() {
    return(discountCode);
  }

  public void setDiscountCode(double discountCode) {
    this.discountCode = discountCode;
  }

  public int getNumItems() {
    return(numItems);
  }

  public void setNumItems(int numItems) {
    this.numItems = numItems;
  }

  // In real life, replace this with database lookup.

  public double getItemCost() {
    double cost;
    if (itemID.equals("a1234")) {
      cost = 12.99*getDiscountCode();
    } else {
      cost = -9999;
    }
    return(roundToPennies(cost));
  }

  private double roundToPennies(double cost) {
    return(Math.floor(cost*100)/100.0);
  }

  public double getTotalCost() {
    return(getItemCost() * getNumItems());
  }
}