The Model-View-Controller Architecture and XML

I introduced you to Swing's usage of the Model-View-Controller (MVC) paradigm in the previous section. Though well suited for the design of graphical user interface components, the MVC architecture scales upward to applications and even systems. It is important to understand where XML fits in this picture, from Swing components on up.

Figure 7.3 is a high-level representation of the MVC architecture. The key elements of the diagram are the one-to-many relationships between the model and the controllers and the model and the views. Of course, the model being the abstract representation of some data correlates perfectly with XML as the premiere format for structured data. Another interesting artifact of the MVC architecture is its suitability for distributed applications. The connections between model, views, and controllers can span multiple applications, hosts and networks (including the Internet). So again, the distributed nature of MVC correlates well with the Web-centric domain of XML.

Figure 7.3. The MVC architecture.


The Swing components use models to allow multiple components to view and react to a single data structure. Many, but not all, Swing components use a model. Table 7.1 lists all the Swing components, describes them, and lists any models they use.

Table 7.1. Swing Component Models
Component Model Description
JApplet None An extension of an applet to allow Swing MenuBars and multiple panes.
JButton ButtonModel A pushbutton.
JCheckBox ButtonModel A check box (item that maintains state).
JCheckBoxMenuItem ButtonModel A menu item that can be selected or deselected.
JColorChooser ColorSelection A set of controls in a pane to allow the selection of a color.
JComboBox CombBoxModel A combo box (combination of a text field and a drop-down list).
JComponent None Base class for all Swing components.
JDesktopPane None Container used to create a multiple document object (MDI) desktop.
JDialog None A dialog window for both custom and standard dialog boxes.
JEditorPane Document A text component to edit a pluggable content type(using an EditorKit implementation).
JFileChooser None A dialog box to select a file to open or save.
JInternalFrame None A MDI window inside a JDesktopPane.
JLabel None A static text string or image that does not react to events.
JLayeredPane None A component to add depth to a container via multiple layers.
JList ListSelection ListModel A list of objects (text or images).
JMenu ButtonModel A menu in either a menu bar or popup menu.
JMenuBar SingleSelectionModel A menu bar.
JMenuItem ButtonModel A menu item.
JOptionPane None A standard set of dialog boxes to prompt the user.
JPanel None An invisible container for other components.
JPasswordField Document A text field that does not echo characters.
JPopupMenu SingleSelectionModel A popup menu (menu that pops up with a right click).
JProgressBar BoundedRange A graphical bar that displays the progress of some action.
JRadioButton ButtonModel A radio button (item that displays its state and can belong to a group).
JRadioButtonMenuItem ButtonModel A group of menu items of which only one can be selected.
JRootPane None The root of all JFC windows/panes.
JScrollBar BoundedRange A scrollbar (a knob to set a viewable display area).
JScrollPane None A container that automatically manages scrollbars for its contents.
JSeparator None A menu separator.
JSlider BoundedRange A slider (a slidable knob within a bounded interval).
JTabbedPane SingleSelectionModel A component that allows switching between panes (tabbed folder metaphor).
JTable TableModel TableColumn ListSelection A two-dimensional spreadsheet view.
JTextArea Document A multi-line editing area.
JTextField Document A single-line editing area.
JTextPane Document An extension of editor pane that models paragraphs and styles.
JToggleButton ButtonModel A two-state button.
JToolBar None A button bar with image buttons for common actions.
JToolTip None A "tip" display for all components when the mouse "hovers" over it.
JTree TreeModel TreeSelection A display for hierarchical data.
JViewPort None A viewable area (porthole) in a window that can be changed via scrolling.
JWindow None A window with no title bar.

The model this section focuses on is TableModel in Listing 7.4. TableModel abstracts a two-dimensional table of data with columns, rows, and a header line of column names. Any object that implements this interface can be rendered with a JTable.

Code Listing 7.4. TableModel.java
package javax.swing.table;
import javax.swing.*;
import javax.swing.event.*;

public interface TableModel
{
    public int getRowCount();
    public int getColumnCount();
    public String getColumnName(int columnIndex);
    public Class getColumnClass(int columnIndex);
    public boolean isCellEditable(int rowIndex, int columnIndex);
    public Object getValueAt(int rowIndex, int columnIndex);
    public void setValueAt(Object aValue, int rowIndex, int columnIndex);
    public void addTableModelListener(TableModelListener l);
    public void removeTableModelListener(TableModelListener l);
}

The DomTable Application

The DomTable application wraps a DOM in a table model and produces Figure 7.4 for myaddresses.xml. To execute the DomTable application you type:

Figure 7.4. A DOM presented in table form.


> java sams.chp7.DomTable myaddresses.xml ADDRESS

When run, the code generates the output shown in Figure 7.4.

The features of the DomTable application are as follows:

  • Accepts any XML document to render in a table. The only constraint is that the user specifies one element (referred to as a recordTag in the program) to equate to a record (or row of the table). The chosen record element can be arbitrarily nested in the XML document because the list of rows (or candidate elements) is created by traversing the entire tree.

  • The elements subelements become the columns of the table.

Code Listing 7.5. DomTable.java
/* DomTable.java */
package sams.chp7;

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import com.sun.xml.tree.XmlDocument;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.w3c.dom.*;

public class DomTable extends JFrame
{
    XmlDocument doc;

    public Insets getInsets()
    {
        return new Insets(25,5,5,5);
    }

    class DomTableModel extends AbstractTableModel
    {
        Document doc;
        ArrayList listeners = new ArrayList();
        NodeList records, columns;

        public DomTableModel(Document doc, String recordTagName)
        {
            this.doc = doc;
            records =
              doc.getDocumentElement().getElementsByTagName(recordTagName);
            columns = records.item(0).getChildNodes();
        }

        // Table model methods
        public int getRowCount()
        {
            return records.getLength();
        }

        public int getColumnCount()
        {
            // subelements of this element
            return columns.getLength();
        }

        public String getColumnName(int column)
        {
            return columns.item(column).getNodeName();
        }
        public Object getValueAt(int row, int column)
        {
            Node n = records.item(row);
            NodeList nl = n.getChildNodes();
            Node n2 = nl.item(column);
            String val = n2.getNodeValue();
            if (val == null)
            {
                // Node is an element
                // get text node
                Node n3 = n2.getFirstChild();
                if (n3 != null)
                    val = n3.getNodeValue();
            }

            return val;
        }
    }


    public DomTable(String fileName, String recordTagName) throws Exception
    {
        super(recordTagName + " Table");

        // create a SAX InputSource
        InputSource is = new
                         InputSource(new File(fileName).toURL().toString());
        // create a DOM Document
        doc = XmlDocument.createXmlDocument(is, true);
        DomUtil.normalizeDocument(doc.getDocumentElement());

        // create a DomTableModel
        DomTableModel dtm = new DomTableModel(doc, recordTagName);

        // Create a Table
        JTable tbl = new JTable(dtm);

        // Create a scroll pane
        JScrollPane scroll = new JScrollPane(tbl);

        getContentPane().add("Center", scroll);

        addWindowListener(new WindowAdapter()
                          {
                            public void windowClosing(WindowEvent we)
                            { System.exit(1); }
                          });

        setLocation(100,100);
        setSize(600,400);
        setVisible(true);
    }

    public static void main(String args[])
    {
        if (args.length < 2)
        {
            System.out.println("USAGE: java sams.chp7.DomTable xmlfile recordTag");
            System.exit(1);
        }

        try
        {
            new DomTable(args[0], args[1]);
        } catch (Throwable t)
          {
            t.printStackTrace();
          }
    }
}

Note the following points about Listing 7.5:

  • The main() method passes two command-line arguments (XML filename and record element) to the constructor of a DomTable object. The DomTable extends a JFrame and contains a JTable component.

  • The DomTable constructor parses the XML document to create a DOM document (XmlDocument object in Sun's implementation) and then instantiates a DomTableModel. The DomTableModel constructor takes two arguments—a document reference and a string for the recordTagName (the element name representing a row). The DomTableModel is the most important object in the program and is discussed in detail in the next bullet. The DomTableModel is passed as an argument into the JTable constructor. The JTable is inserted into a JScrollpane and added to the content pane of the JFrame. Lastly, the JFrame is sized and displayed.

  • The DomTableModel extends AbstractTableModel, which handles four of the nine methods in the TableModel interface. The DomTableModel class implements the other five methods of the TableModel interface. In general, the table model is responsible for providing the number of rows and the value of each cell (row,column) in the table. You can optionally provide a number of columns (getColumnCount()) and the names of those columns (getColumnName()). The methodology used to provide the rows and columns for the table is to get a list of the chosen elements (specified in the recordTagName parameter), where each element is a row. The number of children in the first element designates the columns. This is not a foolproof method to obtain the columns. A better method would be to iterate through all the elements and create a superset of all subelement names in all the records in the record list. This improvement is left to you as an exercise. The key method in the object is the getValueAt() method which retrieves the value of the text node for the specified row and column. Another potential improvement to the program is to allow columns to be attributes, subelements, or both.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.183.89