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]