Chapter 5 continued. Web Site Manager - Design and Implementation

In the previous chapter, we developed a use-case analysis of the Web Site Manager. In this chapter, we’ll use that analysis to guide a design and implementation.

 

Our approach:

·        Flesh out the design model

·        Implement the graph and tool models, then their user interfaces

·        Add in the tree system, and its user interface

·        Discuss how we’ve used an old framework, and defined a new framework.

 

We’ll develop the model before the user interface, because the user interface is almost always “most likely to change.” (Should it be a GUI? Should it use Swing or AWT? Should the current node be on top? Is green the right color for this?) The object model is more stable: the system will still be a web site manager if it doesn’t use Swing, but not if it no longer deals with web sites.

 

Design Model

The screen design reflects three parts of the program:

 

 

We have three models to merge:

·        Analysis object model

·        Selection model

·        Graph framework

 

We’ll begin by adopting the object model from analysis, and see how it looks.

 

 

 

The Tool needs to know its Site. Also, we’d like to know the Tool’s name. We didn’t identify this as a property before. (So, we’ll add a method “String getName()” to Tool.)

 

Design Model - Selection

“A page is selected, and tools operate on it.” The page is important, and so is the tool, but realizing that a selection relates the two together is key.

 

[KEY] The analysis model didn’t emphasize the idea of a “current page”, but it is crucial to the design. The current page represents the focus of all three screen areas.

 

One approach to defining how selection might work would be to define a PageSelectionModel, a PageSelectionListener, and a PageSelectionEvent, suitable for use with JavaBeans. It might not be a bad approach. But, even while designing one framework, we keep our eyes out for other frameworks.

 

Selection is generally useful, so we’ll introduce a “micro framework” for selection:

                SelectionModel: tracks a selected object.

                SelectionListener: listens for changes in selection.

                SelectionEvent: notification of change in selection. [TBD needed?]

                DefaultSelectionModel: an implementation

 

These objects will connect like this:

 

 

When an object is selected, the model notifies the listeners of the change.

 

This object, focused on generic selection, may not be as type-safe as a version focused on pages, but it enables generic components to hook together with fewer adapters and fewer types overall.

 

Once we have these objects, we are following the JavaBeans version of the Observer pattern.

 

 

How did we know to use this pattern? By sweat work: trying a number of configurations, until it became obvious that all three screen areas were viewing the same thing. This is a classic arrangement that can make use of the Observer pattern.

 

Design Model - Graph

We’d like to use our Graph framework to support the graph nature of the web. The first step is to identify the relationships between Graph classes and web site manager objects:

                Graph: Site

                Node: Page

                Edge: Links to other pages

 

 

[TBD]

In Graph, do we need some sort of invalidate() command? (caching)

 

 

Design Model - Putting It All Together

[TBD] A. Unified model

 

[TBD] B. Mapping to Java

These could be mapped as classes or interfaces.

 

[KEY] Use interfaces for interesting objects, and classes for blobs of data.

 

In our case, a URL is mostly a “data bag”, so we’ll make it a simple class. (We might decide to just use java.net.URL.)

 

public class URL {

      private String name;

      public URL(String name) {this.name = name;}

      public String toString() {return name;}

}

 

Site, Page, and Tool have more interesting behavior, so they will be interfaces.

 

 

 

[TBD] C. Interconnection model

 

The model for interconnecting the pieces:

User Interface, V1

At this point, we can turn two teams loose in parallel: one for implementation of the model, the other to develop the user interface. At the end, we’ll integrate their efforts.

 

 

It’s helpful to “burst” this view apart, to see what could build it in terms of UI widgets.

 

 

 

The Tool needs an on-screen representation (as a JComponent in this case).

 

The easy way out is to add a method to Tool: public void JComponent getComponent(). Then the user interface could ask for a tool, and ask the tool for its component.

 

[KEY] Couple the user interface to the model, not the model to the user interface.

 

We don’t want to depend “up”. So, we’ll temporize, and assume there is a ToolComponentMap object, with a method getComponent(Tool) that will find the component for us.

 

[TBD - defer commitment - Thimbleby]

 

The code for the panels is straightforward if tedious:

[TBD - keep?]

 

public URLPanel() {

      setLayout(new BorderLayout());

      add(new Jlabel(“URL”), “West”);

      add(textfield, “Center”);

      add(button, “East”);

      button.addActionListener(new ActionListener() {…});

      textfield.addActionListener(new ActionListener() {…});

}

 

public ToolPanel() {

      setLayout(new BorderLayout());

      add(Tool[0], “Center”);

}

 

public WSMPanel() {

      setLayout(new BorderLayout());

      add(new URLPanel(), “North”);

      add(new ToolPanel(), “Center”);

}

 


Current Node

We’re trying to support this piece:

                [TBD - current node, in, & out]

 

This is really just a view on the Node object.

 

Notice that we can access the current page name (via toString()), and the in and out nodes (and their names). Thus, we can entirely display these items without even caring that they’re Pages (or Nodes).

 

[NOTE Box] Wait a minute!

We’ve talked about the display, the file tree, and the current node. None of them cared that these were web pages! Can this be right?

 

Yes, it is, and it reflects a philosophical goal: keep things decoupled. At some point, yes, we must deal with HTML. But by avoiding the dependency as much as possible, we let other pieces continue development in parallel.

 

Node selection

JList inList = list of Node

JList outList = list of Node

 

setCellRenderer (ListCellRenderer)

setNodeRenderer (Renderer)

                (with defaults)

 

See CellRendererPane.

 

Setup list listeners. On click, make the selection be the current node.

 

                setSelection(Object)

                                (is null ok? Yes - can deselect all nodes)

 

TBD - more on design.

 

 

 

WebGraph Implementation

 

                URL   File  Edges

 

Relative to a "base" that defines a prefix for the URL and the file.

 

Given a file, relative to “base,”  find its Edges. We'll let Graph take File. Each File will generate a node. We'll use a StreamTokenizer to look for "<A HREF="...">" occurrences. This is not full HTML parsing by any stretch. It's just a quick-and-dirty way to get the easy 95%.

 

WebBase

                String filePrefix

                String webPrefix

 

Tools

File Info Viewer

                name-value pairs

                Readable: true

                Writable: true

                Length: int

 

HTML Viewer

                []

Need: ability to change node.

 

 

The tool display is where we see this application acting as another framework. The idea is that we'll provide a design that can accommodate a number of tools.

 

 

Each tool will provide a panel that we can add to the tab pane.

 

What does the tool look like?

 

We'll require it to be a subclass of JComponent, so it can be put in the tab pane. We'd also like to know its name, and a tooltip name for it.

[TBD ??]

 

What does the tool need to know? It needs to know which page it's working on.

 

[Later - revoke the subclass idea - provide a method to return JComponent.]

 

[Design with no central object - revoke later]

 

 

A tool now has these characteristics:

                name

                tooltip text (long name) (description)

                ObjectSelectionListener

                (and it's a JComponent)

 

Wait! Is a tool a component, or does it have a component?

 

[TBD - no]

It's almost certainly better to make the tool provide the component when asked. This will let us keep "being a tool" an interface. It will let us use existing components rather than forcing them to be in a particular spot in the class hierarchy.

 

                public interface Tool extends ObjectSelectionListener {

                                public String getName();

                                public String getDescription();

                                public JComponent getComponent();

                }

 

[TBD - easier to wrap]

 

Now the toolbox:

                public interface Toolbox extends ObjectSelectionListener {

                                public void add(Tool);

                                public void remove(Tool);

                }

 

 

                Toolbox <> ---- Tool

 

Quickie implementation: use Vector & JTabbedPane.

 

 

Tree Model

For the moment, let’s ignore all the stuff about graphs, webs, and HTML, and take a detour. We’ll develop a component we might have had lying around: a tree of Files, corresponding to a directory hierarchy. (Many applications could use a tree widget based on the file system.)

 

The Swing library has an interface we will use: TreeModel. We’ll conform to that interface, and provide a concrete implementation focused on files. (As we’ll see later, Swing has been a bit sloppy about package dependencies; this forces us to depend on a GUI library for a basic data structure.)

 

To build a tree of files using Swing, it's most natural to put them in a JTree object. The JTree requires a TreeModel, which is the data model (as in model-view-controller). This will correspond to the directory hierarchy.

 

The TreeModel is a Tree of File objects, corresponding to the structure on disk. (Notice that we need this - not all pages are linked together, and a tree view is often convenient.)

 

[TBD G - model]

 

We want to work with File objects, but a TreeModel works with TreeNodes. We will wrap our files into a TreeNode by implementing that interface:

 

[tbd]

 

We want to be somewhat careful in creating the tree. Since filesystems can be large, we don't want to load the whole tree all at once. Instead, we only want to load the nodes as needed. Thus, the first step of most routines will be to ensure that the children (if needed) are present.

We want to be lazy in creating trees. Since a file system is potentially large, we don’t want to load it all at once. Instead, we’ll load nodes as needed. Thus, most routines will instantiate their children on demand.

 

[TBD] check isDirectory() once

 

Here’s a sample listener to verify our widget.

 

Here’s a demo GUI for it. [TBD JTree]

 

Problem: TreeModel and its base.

 

We can put it in the JTree like this:

[Code tbd]

 

Here's simple driver code so you can test this:

[Code tbd]

 

We can add a SelectionListener to print the current file:

[Code tbd]

 

So - we have one part "done"!

 

Backtrack - TreeModel knows "base".

 

We could define the display for those items, and let subclasses override the display methods if they want to be different. That would be a white-box approach. Instead, we'll take a more black-box approach, and have the idea of renderers, small pieces of code that handle the display of a single item. (Swing does this for lists, tables, etc.)

 

[TBD - picture]

 

We'll provide default renderers that just do "node.toString()" to get the value.

 

 

 

The Adapter

[TBD]

 

The file structure wasn’t really mentioned before, but we need to deal with pages not just as they’re linked, but also as they’re stored.

 

We have to relate the files contained in the tree to the pages in our web.

 

The adapter will have to know a relationship, e.g.,

                http://node/dir == /home/web/dir

(to realize that http://node/ maps to /home/web/.) On the web side, the Nodes will be Pages.

 

 

 

 

HTML (At Last!)

How do we find HTML nodes?

 

Files ending in .htm, .html, or .shtml.

 

<A HREF=”string”>

                capture the filename using StringTokenizer

 

<[Aa][ \t]+[Hh][Rr][Ee][Ff][ \t]*=[ \t]*”[^”]*”>

 

HTMLGraph package  --------à Graph package

HTMLGraph ->                     Graph

HTMLEdge ->                      Edge

HTMLNode ->                      Node

 

Design Revisited

 

Earlier, we described the notification from Graph to FileTree to toolbox, etc.

 

A useful technique for evaluating designs is to consider the most likely changes, and see how well the design stands up to them.

 

The most likely change is a new tool. We handle this fairly well - all that's required is a new Tool subclass. Another Java application could be adapted fairly easily.

 

Another change might be a new web representation. We have three already: FileTree, Graph, and Tool. There's an old design rule "0, 1, infinity." It tells you that once you have two or more of something, then you need to consider the possibility of even more.

 

Another change might be moving to XML. [etc]

 

 

 

 

Copyright 1994-2006, William C. Wake - William.Wake@acm.org