Day Planner Applicarion

TABLE OF CONTENTS

  1. planner.dtd .
    Document type defintion file for the day planner application.
  2. planner.xml .
    XML markup file for the day planner application.
  3. DayPlanner.java .
    Defines GUI interface for the day planner application.
  4. DOMPlanner.java .
    Uses DOM to build tree of planning activities. Also contains code for querying and searching the DOM tree.
  5. MyErrorHandler.java .
    Error handling for validation errors.


planner.dtd
    <!-- Fig. 6.14: planner.dtd -->
    <!-- DTD for day planner    -->  

    <!ELEMENT planner ( year* )>

    <!ELEMENT year ( date+ )>
    <!ATTLIST year value CDATA #REQUIRED>

    <!ELEMENT date ( note+ )>
    <!ATTLIST date month CDATA #REQUIRED>
    <!ATTLIST date day CDATA #REQUIRED>

    <!ELEMENT note ( #PCDATA )>
    <!ATTLIST note time CDATA #IMPLIED>


planner.xml
    <?xml version = "1.0"?>
    <!-- Travel Planner XML document -->
    <!DOCTYPE planner SYSTEM "planner.dtd">

    <planner>
        <year value = "2001">
           <date month = "12" day = "22">
              <note time = "0630">Go to airport             </note>
              <note time = "0930">Catch flight to Vancouver </note>
           </date>
        </year>

        <year value = "2002">

           <date month = "1" day = "3">
              <note time = "1430">Catch flight to Washington DC </note>
           </date>

           <date month = "1" day = "8">
              <note time = "0830">Leave Washington DC for New Zealand </note>
           </date>

           <date month = "1" day = "10">
              <note time = "0800">Arrive in Auckland, New Zealand   </note>
              <note time = "1130">Arrive in Queenstown, New Zealand </note>
           </date>

           <date month = "1" day = "22">
              <note time = "1700">Leave Queenstown for Washington DC </note>
              <note time = "1200">Meet Jim at LAX for a drink        </note>
              <note time = "2000">Arrive back in Washington DC       </note>
           </date>

           <date month = "3" day = "22">
              <note time = "2030"> Leave Washington DC for Sweden </note>
           </date>

           <date month = "3" day = "30">
              <note time = "0800"> Leave Copenhagen for Washington DC </note>
           </date>
        </year>
    </planner>


DayPlanner.java
/*
 *  ===========================================================================
 *  DayPlanner.java: Program for GUI interface for the day planner application.
 *  
 *  Code developed by Deitel and Deitel, 2000.
 *  Code slightly modified for JAXP: By Mark Austin                 March, 2002
 *  ===========================================================================
 */

import java.awt.*;                  
import java.awt.event.*;            
import javax.swing.*;               
import javax.swing.event.*;

public class DayPlanner extends JFrame implements ActionListener {

   // GUI components

   private JTextArea display;
   private JComboBox year, month, day, time;
   private JButton   query;
   private JPanel panel1, panel2;
   private DOMPlanner handler;

   public DayPlanner() {

      super( "DOM-Based Travel Planner" );

      // Set the output font      

      Font font = new Font( "Monospaced", java.awt.Font.BOLD, 16 );
      display   = new JTextArea();
      display.setFont( font );
      display.setEditable( false );
      
      handler = new DOMPlanner( display );

      // Initialize the user interface components    

      year = new JComboBox( handler.getYears() );

      String months[] = new String[ 13 ];
      months[ 0 ]     = "ANY";

      for ( int i = 1; i < 13; i++ )
         months[ i ] = Integer.toString( i );

      month = new JComboBox( months );

      String days[] = new String[ 32 ];
      days[ 0 ] = "ANY";

      for ( int i = 1; i < 32; i++ )
         days[ i ] = Integer.toString( i );

      day = new JComboBox( days );

      String times[] = {      "ANY",
                          "Morning",
                        "Afternoon",
                          "Evening",
                            "Night" };

      time = new JComboBox( times );

      // Create "Get Schedules" button and attach listener.

      query = new JButton( "Get Schedules" );
      query.addActionListener( this );

      // Panel containing components for querying

      panel1 = new JPanel();
      panel1.setLayout( new GridLayout( 4, 2 ) );
      panel1.add( new JLabel( "Year" ) ); 
      panel1.add( year );
      panel1.add( new JLabel( "Month" ) ); 
      panel1.add( month );
      panel1.add( new JLabel( "Day" ) ); 
      panel1.add( day );
      panel1.add( new JLabel("Time") ); 
      panel1.add( time );

      // Panel containing text area for output
      // and panel2 containing other GUI components.

      panel2 = new JPanel();
      panel2.setLayout( new GridLayout( 1, 2 ) );
      panel2.add( panel1 );      
      panel2.add( query );      

      // Arrange panels on content pane using border layout.....

      Container c = getContentPane();
      c.setLayout( new BorderLayout() ); 
      c.add( new JScrollPane( display ), BorderLayout.CENTER );
      c.add( panel2, BorderLayout.SOUTH );

      // Size and display frame....

      setSize( 700, 450 );
      show();
   }

   // Method executed when query button is pressed

   public void actionPerformed( ActionEvent e ) {

      if ( e.getSource() == query ) {
         int yearIndex, monthIndex, dayIndex, timeIndex;

         // Get the integer values of all the query parameters

         yearIndex  = getIntegerValue( ( String ) year.getSelectedItem() );
         monthIndex = getIntegerValue( ( String ) month.getSelectedItem() );
         dayIndex   = getIntegerValue( ( String ) day.getSelectedItem() );
         timeIndex  = time.getSelectedIndex() - 1;

         // Get the result of query

         handler.getQueryResult( yearIndex, monthIndex,
                                 dayIndex, timeIndex );
      }
   }

   // Method to convert the string value to integer

   public int getIntegerValue( String str ) {

      // If the value 'ANY' is selected, return -1

      if ( str.equals( "ANY" ) )
         return -1;
      else
         return Integer.parseInt( str );

   }

   // Main method for Day Planner application.....

   public static void main( String s[] ) {

      // Create instance of DayPlanner().....

      DayPlanner d = new DayPlanner();

      // Setup (inner class) listener to close window.....

      d.addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent e ) {
               System.exit( 0 );
            }
         }
      );
   }
}


DOMPlanner.java
/*
 *  ===========================================================================
 *  DOMPlanner.java: A day planner application using DOM.
 *  
 *  Code developed by Deitel and Deitel, 2000.
 *  Code slightly modified for JAXP: By Mark Austin                 March, 2002
 *  ===========================================================================
 */

import java.io.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;

import org.w3c.dom.*;
import org.xml.sax.*;
import javax.xml.parsers.*;

public class DOMPlanner {
  
   private JTextArea display;    // for displaying output
   private InputSource input;    // for reading the XML document
   private Document document;    // document node object

   // Variables to store the query parameters and the result

   private int year, month, day, timePeriod; 
   private String resultYear, resultDay;

   public DOMPlanner( JTextArea output ) {

      year    = month = day = timePeriod = -1;
      display = output; 

      try {

         // Obtain the default parser

         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setValidating( true );
         DocumentBuilder builder = factory.newDocumentBuilder();

         // Set error handler for validation errors

         builder.setErrorHandler( new MyErrorHandler() );

         // Obtain Document Object from XML Document

         document = builder.parse( new File( "planner.xml" ) );
      } 

      // Catch errors .....

      catch ( SAXParseException spe ) {
         System.err.println( "Parse error: " + 
            spe.getMessage() );
         System.exit( 1 );
      }

      catch ( SAXException se ) {
         se.printStackTrace();         
      }

      catch ( FileNotFoundException fne ) {
         System.err.println( "File \"planner.xml\" not found." );
         System.exit( 1 );
      }

      catch ( Exception e ) {
         e.printStackTrace();
      }
   }

   // Method to get the available years from the XML file

   public String[] getYears() {

      String availableYears[];   
      StringTokenizer tokens;
      String str = " ";
      int i = 0;

      Element root = document.getDocumentElement();
      NodeList yearNodes = root.getElementsByTagName( "year" );

      // Get value of attribute 'value' for each 'year' node

      for ( i = 0; i < yearNodes.getLength(); i++ ) {
         NamedNodeMap yearAttributes = yearNodes.item(i).getAttributes();

         str += " " + yearAttributes.item( 0 ).getNodeValue();
      }  

      tokens = new StringTokenizer( str );
      availableYears = new String[ tokens.countTokens() + 1 ];
      availableYears[ 0 ] = "ANY";
      i = 1;

      // Form an array of strings containing available years

      while ( tokens.hasMoreTokens() )
         availableYears[ i++ ] = tokens.nextToken();

      return availableYears;
   }

   // method to initialize the query

   public void getQueryResult( int y, int m, int d, int t ) {

      year       = y;
      month      = m;
      day        = d;
      resultYear = "";
      resultDay  = "";
      timePeriod = t;
      display.setText( "*** Mark Austin's Travel Planner ***" );
      getResult( document );

   }   

   // Method to output the result of query

   public void getResult( Node node ) {

      // Recursively process each type of node...

      switch ( node.getNodeType() ) {

         // If it is a Document node process its children

         case Node.DOCUMENT_NODE:
              Document doc = ( Document ) node;
              getResult( doc.getDocumentElement() );
              break;

         // Process element node according to its tag name

         case Node.ELEMENT_NODE:

              if ( node.getNodeName().equals( "planner" ) )
                 processChildNodes( node.getChildNodes() );
              else if ( node.getNodeName().equals( "year" ) ) {
  
                 // find the attribute value for year and 
                 // check if it matches the query

                 NamedNodeMap yearAttributes = node.getAttributes();
                 Node value = yearAttributes.item( 0 );

                 if ( Integer.parseInt( value.getNodeValue() ) == year || year == -1 ) {
                      resultYear = " Y " + Integer.parseInt( value.getNodeValue() );
                      processChildNodes( node.getChildNodes() );
                 } else
                      return;  

              } else if ( node.getNodeName().equals( "date" ) ) {
                 Element dateElement = ( Element ) node;
                 int m = Integer.parseInt( dateElement.getAttribute( "month" ) );
                 int d = Integer.parseInt( dateElement.getAttribute( "day" ) );

                 // Check if the current 'date' node satisfies query

                 if ( ( m == month && d == day )  || ( month == -1 && d == day ) ||
                      ( m == month && day == -1 ) || ( month == -1 && day == -1 ) ) {
                      resultDay = "DATE: D " + d + " M " + m ;
                      processChildNodes( dateElement.getChildNodes() );
                 } else
                      return;

              } else if ( node.getNodeName().equals( "note" ) ) {

                 // Fetch attributes for the note node and
                 // verify its attribute values with the query

                 NamedNodeMap noteAttributes = node.getAttributes();

                 int scheduleTime;

                 if ( noteAttributes.getLength() != 0 ) {
                      Node nodeTime = noteAttributes.item( 0 );

                      scheduleTime = Integer.parseInt( nodeTime.getNodeValue() );
                 } else
                      scheduleTime = -1;

                 // If the time lies between the periods of the
                 // day display the value of node 'note'

                 if ( isBetween( scheduleTime ) )  {
                      Node child = ( node.getChildNodes() ).item( 0 );
                      String s = child.getNodeValue().trim();     

                      display.append( "\n" + resultDay + resultYear );

                      if ( scheduleTime != -1 )
                          display.append( "\nTIME: " + scheduleTime +" > " + s );
                      else
                          display.append( "\nALL DAY > " + s ); 

                     display.append( "\n* * * * * * * * * *" );
                 } else
                     return;
              }
              break;
      }
   }

   // Method to process child nodes

   public void processChildNodes( NodeList children ) {

      if ( children.getLength() != 0 )
         for ( int i = 0; i < children.getLength(); i++ )
               getResult( children.item( i ) );

      return;
   }

   // Method to compare the time with various periods of the day

   public boolean isBetween( int time ) {

      switch ( timePeriod ) {
         case -1:         // add day
            return true;
         case  0:         // morning
               if ( time >= 500 && time < 1200 )
                  return true;
               break;
          case 1:         // afternoon
               if ( time >= 1200 && time < 1800 )
                  return true;
               break;
          case 2:         // evening
               if ( time >= 1800 && time < 2100 ) 
                  return true;
               break;
          case 3:         // night
               if ( time >= 2100 || time < 500 )
                  return true;
               break;
          default:
               System.out.println( "Illegal time in XML file" );
      }

      return false;
   }
}


MyErrorHandler.java
/*
 *  ===========================================================================
 *  MyErrorHandler.java: Error Handler for validation errors.
 *  
 *  Code developed by Deitel and Deitel.                                   2000.
 *  ===========================================================================
 */

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class MyErrorHandler implements ErrorHandler {

   // Throw SAX Exception for fatal errors

   public void fatalError( SAXParseException exception ) throws SAXException {
      throw exception;
   }

   public void error( SAXParseException e ) throws SAXParseException {
      throw e;
   }

   // Print any warnings 

   public void warning( SAXParseException err ) throws SAXParseException {
      System.err.println( "Warning: " + err.getMessage() );
   }

}

Developed in April 2002 by Mark Austin
Copyright © 2002, Mark Austin, University of Maryland