Language selection

Search

Patent 2209265 Summary

Third-party information liability

Some of the information on this Web page has been provided by external sources. The Government of Canada is not responsible for the accuracy, reliability or currency of the information supplied by external sources. Users wishing to rely upon this information should consult directly with the source of the information. Content provided by external sources is not subject to official languages, privacy and accessibility requirements.

Claims and Abstract availability

Any discrepancies in the text and image of the Claims and Abstract are due to differing posting times. Text of the Claims and Abstract are posted:

  • At the time the application is open to public inspection;
  • At the time of issue of the patent (grant).
(12) Patent Application: (11) CA 2209265
(54) English Title: APPARATUS AND METHOD FOR INFORMATION RETRIEVAL VIA INTERNET
(54) French Title: APPAREIL ET METHODE D'EXTRACTION D'IN FORMATIONS VIA L'INTERNET
Status: Dead
Bibliographic Data
(51) International Patent Classification (IPC):
  • G06F 16/953 (2019.01)
  • G06F 16/955 (2019.01)
(72) Inventors :
  • TELFORD, ROBERT (Not Available)
  • EVANS, GARY (Not Available)
  • DUNCAN, BRIAN (Not Available)
(73) Owners :
  • THE COMPUTER GROUP, INC. (United States of America)
(71) Applicants :
  • THE COMPUTER GROUP, INC. (United States of America)
(74) Agent: GOWLING WLG (CANADA) LLP
(74) Associate agent:
(45) Issued:
(22) Filed Date: 1997-06-27
(41) Open to Public Inspection: 1998-08-27
Availability of licence: N/A
(25) Language of filing: English

Patent Cooperation Treaty (PCT): No

(30) Application Priority Data:
Application No. Country/Territory Date
08/807,474 United States of America 1997-02-27

Abstracts

English Abstract





The present invention relates to apparatus and method for
retrieving information via an interactive computer network
such as the Internet. Apparatus and methods are provided that
permit Web clients to intelligently search secondary Web
servers that have data matching the Web client's search
criteria and retrieve specified data from such secondary Web
servers, without the need for the Web client to specify the
uniform resource locators, (URL's) of the secondary Web
servers. Furthermore, apparatus and methods are provided that
enable users of an interactive computer network to search for
information in a specific context rather than searching for
information by merely matching words without regard to the
context in which the words are used in the information.


French Abstract

La présente invention porte sur des appareils et des méthodes servant à extraire des informations via un réseau informatique interactif tel que l'Internet. L'invention offre des appareils et des méthodes qui permettent aux clients Web d'explorer intelligemment les serveurs Web secondaires qui ont des données correspondant aux critères de recherche du client Web et d'extraire des données particulières de ces serveurs secondaires sans que ce client ait à fournir les localisateurs de ressources uniformes (URL) de ces serveurs secondaires. Elle offre également des appareils et des méthodes qui permettent aux utilisateurs d'un réseau informatique interactif de chercher des informations dans un contexte particulier plutôt que de chercher ces informations en comparant les mots sans tenir compte du contexte dans lequel ces mots sont utilisés dans ces informations.

Claims

Note: Claims are shown in the official language in which they were submitted.




WHAT IS CLAIMED IS:

1. A method of collecting data from at least one searchable
data base management system of an interactive computer
network including servers, routers and associated searchable
data base management systems operated by the servers and
accessible via the routers, the interactive computer network
being accessible via a viewer running on a first computer
functioning as a client user workstation, the method
comprising the steps of:
activating from the viewer, a user interface agent
associated with a primary server;
processing all communication with said user interface
agent through a primary router running on said primary
server;
processing all communication between said primary
server and the client workstation through said primary
router;
said user interface agent determining the location of
each router capable of accessing a searchable data base
management system;
said user interface agent determining each category
characterizing the information stored in each searchable
data base management system; and
said user interface agent assisting the client user to
formulate a search request in terms of at least one said
category.

202




2. A method as in claim 1, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, includes the step of:
maintaining a cross-reference file accessible by said
primary server, said cross-reference file containing a
category list including at least one category that
identifies the information stored by the data base
management system that is operated by said primary server.

3. A method as in claim 1, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, includes the step of:
said user interface agent sending a TYP Request to said
primary server operating said primary data base management
system, said TYP Request requesting for said primary data
base management system, the theme type that characterizes
the information that is maintained by said primary data base
management system.




203



4. A method as in claim 3, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, further includes the step of:
said primary router receiving said TYP Request,
retrieving from an initialization file maintained by said
primary server, the information satisfying said TYP Request,
formatting the information satisfying said TYP Request into
a TYP Response, and returning said TYP Response to said user
interface agent, said TYP Response including each theme type
that characterizes the information that is maintained by
said primary data base management system.

5. A method as in claim 1, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, includes the step of:
said user interface agent sending a CAT Request to said
primary server operating said primary data base management
system, said CAT Request requesting for said primary data
base management system, each category that characterizes the
information that is maintained by said primary data base
management system.




204




6. A method as in claim 5, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, further includes the step of:
said primary router receiving said CAT Request,
retrieving from a cross-reference file maintained by said
primary server, the information satisfying said CAT Request,
formatting the information satisfying said CAT Request into
a CAT Response, and returning said CAT Response to said user
interface agent, said CAT Response including each category
type that characterizes the information that is maintained
by said primary data base management system.

7. A method as in claim 6, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
further includes the step of:
said user interface agent receiving said CAT Response
and for each category in said CAT Response, said user
interface creating an object corresponding to the type of
said category.

8. A method as in claim 7, wherein said object
corresponding to the type of said category is one of an
object for a DynamicList type of category, an object for a
StaticList type of category, an object for a Single type of
category, and an object for a Range type of category.

205




9. A method as in claim 8, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
includes the step of:
said user interface agent sending a VAL Request to said
primary server operating said primary data base management
system, said VAL Request requesting for said primary data
base management system, each selection to be used to
populate each said StaticList category and each said
DynamicList category specified in said CAT Response.

10. A method as in claim 6, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
includes the step of:
said user interface agent sending a VAL Request to said
primary router, said VAL Request requesting for said primary
data base management system, the selections to be used to
populate at least one category object for a category
specified in said CAT Response.




206




11. A method as in claim 10, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
further includes the step of:
said primary router receiving said VAL Request,
retrieving from said primary data base management system,
the information satisfying said VAL Request, formatting the
information satisfying said VAL Request into a VAL Response,
and returning said VAL Response to said user interface
agent, said VAL Response including each selection to be used
to populate at least one category object for a category
specified in said CAT Response.

12. A method as in claim 11, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
further includes the step of:
said user interface agent receiving said VAL Response
and for each category in said VAL Response, said user
interface agent populating each category object according to
the type of said category.




207




13. A method as in claim 6, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
includes the step of:
said user interface agent sending a VAL Request to a
Hub server operating a Hub data base management system, said
VAL Request requesting for all secondary data base
management systems, the selections to be used to populate at
least one category object for a category specified in said
CAT Response.

14. A method as in claim 13, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
further includes the steps of:
a Hub router receiving said VAL Request, said Hub
router retrieving from said Hub data base management system
operated by said Hub server, the information satisfying said
VAL Request, formatting the information satisfying said VAL
Request into a VAL Response, and returning said VAL Response
to said user interface agent via said primary router, said
VAL Response including each selection to be used to populate
at least one category object for a category specified in
said CAT Response.




208




15. A method as in claim 14, wherein said step of said user
interface agent assisting the client user to formulate a
search request in terms of at least one said category,
further includes the step of:
said user interface agent receiving said VAL Response
and for each category in said VAL Response, said user
interface agent populating each category object according to
the type of said category.

16. A method as in claim 1, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, includes the step of:
said user interface agent sending a HUB Request to said
primary router, said HUB Request requesting the URL for a
Hub server.

17. A method as in claim 16, wherein said step of said user
interface agent determining each category characterizing the
information stored in each searchable data base management
system, further includes the step of:
said primary router receiving said HUB Request,
retrieving from an initialization file maintained by said
primary server, the information satisfying said HUB Request,
formatting the information satisfying said HUB Request into
a HUB Response, and returning said HUB Response to said user
interface agent, said HUB Response including the URL of said
Hub server.




209




18. A method as in claim 1, further comprising the step of:
said user interface agent retrieving information
satisfying the client user's search request formulated with
the assistance of said user interface agent, wherein said
information is retrieved from one of said primary data base
management system alone or said primary data base management
system and other data base management systems operated by
secondary servers.

19. A method as in claim 18, wherein said step of said step
of said user interface agent retrieving information
satisfying the client user's search request, further
comprising the steps of:
said user interface agent sending to said primary
router, a LST Request for information that satisfies the
client user's search request; and
said primary router receiving said LST Request,
retrieving from said primary data base management system,
the information satisfying said LST Request, formatting the
information satisfying said LST Request into a LST Response,
and returning said LST Response to said user interface
agent, said LST Response including at least a predetermined
number of matching records that satisfy the client user's
search request.

20. A method as in claim 19, further comprising the step
of:
said user interface agent presenting on the client
workstation, a display of said matching records in said LST
Response.




210





21. A method as in claim 20, further comprising the step
of:
said user interface agent retrieving and displaying on
the client workstation, additional information than is
provided in one of said matching records chosen by the
client user.

22. A method as in claim 21, wherein said step of said user
interface agent retrieving and displaying on the client
workstation, additional information than is provided in one
of said matching records chosen by the client user,
comprises the step of:
said user interface agent issuing to said primary
router, a request to return the specific URL of an HTML page
that contains additional information than is contained in
said one matching record chosen by the client user.




211




23. A method as in claim 21, wherein said step of said user
interface agent retrieving and displaying on the client
workstation, additional information than is provided in one
of said matching records chosen by the client user,
comprises the steps of:
said user interface agent issuing to said primary
router a HOM Request for the specific URL of an HTML page
that contains additional information than is contained in
said one matching record chosen by the client user;
said primary router receiving said HOM Request and
querying said primary data base management system for
detailed information about said one matching record
specified in said HOM Request;
said primary router building an HTML file from said
detailed information and saving said built HTML file on said
primary server;
said primary router formatting said detailed
information satisfying said HOM Request, into a HOM Response
and sending said HOM Response to said user interface agent;
and
said user interface agent opening a second viewer and
setting said second viewer location to the specific URL of
said built HTML file in said HOM Response.




212




24. A method as in claim 18, wherein said step of said user
interface agent retrieving information satisfying the client
user's search request, includes the step of:
supplying said user interface agent with a profile list
containing the server URL for each of a predetermined number
of secondary servers that operates a data base management
system with data applicable to the client user's search
request and accessible to the client user via said user
interface agent.




213




25. A method as in claim 24, wherein said step of supplying
said user interface agent with a profile list, includes the
steps of:
said user interface agent sending a PRO Request to a
Hub router running on a Hub server operating a Hub data base
management system, said PRO Request containing the client
user's search request and requesting the addresses of less
than a predetermined number of secondary routers that have
access to data base management systems that are listed on a
profile list of said Hub data base management system as
having data matching at least one of the selections that
compose the client user's search request;
said Hub router receiving said PRO Request from said
user interface agent via said primary router;
said Hub router comparing the client user's search
request to said profile list maintained on said Hub data
base management system;
said Hub router selecting URL's that are listed in said
profile list as having data matching at least one of the
selections in the client user's search request;
said Hub router formatting a PRO Response containing
said URL's selected by said Hub router; and
said Hub router returning said PRO Response to said
user interface agent via said primary router.




214




26. A method as in claim 25, wherein said step of said user
interface agent retrieving information satisfying the client
user's search request, further includes the step of:
said user interface agent receiving said PRO Response
and creating a server object corresponding to each URL in
said PRO Response.

27. A method as in claim 26, wherein said step of said step
of said user interface agent retrieving information
satisfying the client user's search request, further
comprising the steps of:
said user interface agent sending to said primary
router, a LST Request for information that satisfies the
client user's search request; and
said primary router sending said LST Request to each
said secondary router associated with each secondary data
base management system associated with each URL in said PRO
Response.

28. A method as in claim 27, wherein said step of said user
interface agent retrieving information satisfying the client
user's search request, further comprising the steps of:
each said secondary router receiving said LST Request,
retrieving from said secondary data base management system
associated with said secondary router, the information
satisfying said LST Request, formatting the information
satisfying said LST Request into a LST Response, and
returning said LST Response to said user interface agent via
said primary router, said LST Response including at least a
predetermined number of matching records that satisfy the
client user's search request.



215




29. A method as in claim 28, further comprising the step
of:
said user interface agent presenting on the client
workstation, a display of said matching records in said LST
Response.

30. A method as in claim 29, further comprising the step
of:
said user interface agent retrieving and displaying on
the client workstation, additional information than is
provided in one of said matching records chosen by the
client user.

31. A method as in claim 30, wherein said step of said user
interface agent retrieving and displaying on the client
workstation, additional information than is provided in one
of said matching records chosen by the client user,
comprises the step of:
said user interface agent issuing to said primary
router, a request to return the specific URL of an HTML page
that contains additional information than is contained in
said one matching record chosen by the client user.




216





32. A method as in claim 30, wherein said step of said user
interface agent retrieving and displaying on the client
workstation, additional information than is provided in one
of said matching records chosen by the client user,
comprises the steps of:
said user interface agent issuing to said primary
router a HOM Request for the specific URL of an HTML page
that contains additional information than is contained in
said one matching record chosen by the client user;
said primary router receiving said HOM Request,
querying said primary data base management system for
detailed information about said one matching record
specified in said HOM Request;
said primary server building an HTML file from said
detailed information and saving said built HTML file on said
primary server;
said primary server formatting said detailed
information satisfying said HOM Request, into a HOM Response
and sending said HOM Response to said primary router;
said primary router sending said HOM Response to said
user interface agent;
said user interface agent opening a second viewer and
setting said second viewer location to the specific URL of
said built HTML file in said HOM Response.

33. A method as in claim 1, further comprising the step of:
said user interface agent retrieving targeted messaging
information related to the client user's search request.




217




34. A method as in claim 33, wherein said step of said user
interface agent retrieving targeted messaging information
related to the client user's search request, includes the
steps of:
said user interface agent sending an ADV Request to a
Hub router running on a Hub server operating a Hub data base
management system, said ADV Request containing the client
user's search request and requesting the URL's of a
predetermined number of HTML files stored on said Hub data
base management system and containing targeted messages that
relate to at least one of the selections that compose the
client user's search request;
said Hub router receiving said ADV Request from said
user interface agent via said primary router;
said Hub router comparing the client user's search
request to said targeted messages maintained on said Hub
data base management system;
said Hub router selecting HTML files that contain
targeted messages relating to at least one of the selections
in the client user's search request;
said Hub router formatting an ADV Response containing
the URL's of said HTML files selected by said Hub router;
and
said Hub router returning said ADV Response to said
user interface agent via said primary router.




218





35. A method as in claim 34, wherein said step of said user
interface agent retrieving targeted messaging information
related to the client user's search request, further
includes the step of:
said user interface agent receiving said ADV Response
and displaying to the client user at least a portion of the
retrieved targeted messaging information in said ADV
Response.

36. A method as in claim 35, wherein said step of said user
interface agent retrieving targeted messaging information
related to the client user's search request, further
includes the step of:
said user interface agent responding to a request of
the client user for more of said retrieved targeted
messaging information in said ADV Response by providing to
the client user the URL in said ADV Response corresponding
to the desired targeted messaging information;
said user interface agent permitting the client user to
open a separate viewer; and
said user interface agent setting said separate viewer
to said URL in said ADV Response corresponding to the
desired targeted messaging information.

37. A method as in claim 33, further comprising the step
of:
each said secondary data base management system
updating said profile list.




219



38. A method as in claim 37, wherein said updating step,
includes the steps of:
each secondary router sending via said primary router,
a COL Request to a Hub router running on a Hub server
operating a Hub data base management system, each said COL
Request containing each category characterizing said
secondary data base management system associated with each
said secondary router and each selection in each said
category;
said Hub router receiving each said COL Request from
said primary router;
said Hub router checking each said COL Request for
validity;
said Hub router updating said profile list according to
each said valid COL Request;
for each said valid COL Request, said Hub router
formatting and sending a COL Response to said primary
router; and
said primary router returning each said COL Response to
each said secondary router from which a valid COL Request
was received.




220




39. A method of making a selection from a plurality of data
base management systems each housed on a computer connected
by an interactive computer network and accessible to the
client user, based on a data request formatted by the client
user via a user interface agent, the method comprising the
steps of:
configuring at least one computer on the interactive
computer network as a Hub server functioning as a URL Hub
for said interactive computer network, said Hub server
serving a searchable Hub data base management system
maintaining on the Hub data base a server profile
containing for each primary and secondary server information
listing each theme type that characterizes the information
that is maintained by each data base management system
available to said client user served by an additional
computer functioning as a server, said profile information
containing each theme type, and for each theme type each
category of information that is maintained on each said data
base management system served by an additional computer
functioning as a server;
maintaining on said primary server an initialization
file containing an initialization list that includes
information for accessing the data base management system of
said server, said Hub server's URL, and each theme type that
characterizes the information that is maintained on the
primary data base management system available to said user
interface agent;
maintaining on each said secondary server an
initialization file containing at least initialization
information for accessing the data base management system
available to said user interface agent;
processing all communication between said primary
server and said Hub server through a Hub router running on
said Hub server; and

221

processing all communication between said user
interface agent through a primary router running on said
primary server.



222

Description

Note: Descriptions are shown in the official language in which they were submitted.


_ CA 0220926~ 1997-06-27


" PATENT
ATTORNEY DOCKET NO.: CGI-l
TITLE OF THE INVENTION
APPARATUS AND METHOD FOR INFORMATION
RETRIEVAL VIA INTERNET
BACKGROUND OF THE INVENI'ION
The present invention relates to apparatus and method
for retrieving information via interactive computer
networks, such as the Internet for example.
Hypertext Markup Language (HTML) is a computer language
that is used to describe textual information accessible via
an interactive computer network such as the Internet. This
information is formatted as a document that is composed of
words, consecutive words forming phrases, consecutive
phrases forming sentences, consecutive sentences forming
paragraphs, consecutive paragraphs forming pages,
consecutive pages forming chapters, and consecutive chapters
forming books, etc.
A person desiring access to information on the Internet
is known as a Web client. To access the Internet, the Web
client must run on the client's computer, a computer program
known variously as a viewer or a browser. Currently, (see
Fig. 1) a Web client makes Hypertext Transmission Protocol
(http) requests for information (files) to a Web Server.
The Web Server will return to the Web client, the HTML file
specified in the client's request. Alternatively, the Web
Server may invoke a Common Gateway Interface (CGI) program
to obtain data satisfying the Web client's request, and then
return this data to the Web client as a formatted HTML file.
Current search engines, like LYCOS for example, are
full text search vehicles in that they compare the search
request against the entire document, word-by-word, without
regard to the context of the word in the search request.
These search engines are computer programs running on a
primary Web server. When such current search engines locate

CA 0220926~ 1997-06-27


the information satisfying the'Web client's search request,
this information is retrieved from the secondary server
where it is found, and transmitted to the primary server
where the information becomes available for review by the
Web client. Because the retrieved information is stored on
the primary server for review by the Web client, the
operator of the secondary server must be willing to permit a
third party, i.e., the operator of the primary server, to
have access to the information stored in the data base
management system associated with the secondary server.
However, many such operators of secondary servers are
reluctant to allow such access.
Moreover, the full text searching that is performed by
such search engines results in retrieval of information
that, while satisfying the search request, includes much
information of a type that is not desired by the Web client.
Accordingly, visits to the web site do not necessarily
indicate a true interest by the visitor. Nor is it possible
to gather information that correlates such visits according
to the specific web site characteristics that were sought by
the visitor.
Another disadvantage with such search engines results
from the way that most commercial enterprises collect and
maintain their information. Most of the information that
commercial enterprises make available on their Web servers,
is originally collected and maintained in column/row
structures or field/record structures. Thus, such
information must be converted to the document structure of
HTML files before such commercial information becomes
searchable by conventional search engines.
OBJECTS AND SUMMARY OF THE INVENTION
It is a principal object of the present invention to
provide apparatus and methods that permit Web clients to
intelligently search secondary Web Servers that have data


- CA 0220926~ 1997-06-27
.. !

matching the Web client's search criteria and retrieve
specified data from such secondary Web Servers, without the
need for the Web client to specify the Uniform Resource
Locators (URLs) of the secondary Web Servers.
It is another principal object of the present invention
to provide apparatus and methods that permit Web clients to
intelligently search remote Web Servers that have data
matching the Web client's search criteria and retrieve
specified structured data from such remote Web Servers,
without the need for the Web client to specify the Uniform
Resource Locators (URLs) of the remote Web Servers.
It is still another principal object of the present
invention to provide apparatus and methods that enable users
of an interactive computer network to search for information
in a specific context rather than searching for information
by merely matching words without regard to the context in
which the words are used in the information.
It is yet another principal object of the present
invention to provide apparatus and methods that enable users
of an interactive computer network to interact with a user
interface that assists the user by intelligently providing
descriptive content and constraints to facilitate
formulation of a structured search query rather than
allowing the user to specify a search query in a manner
likely to return information outside the desired context
sought by the user.
It is a further principal object of the present
invention to provide apparatus and methods that enable users
of an interactive computer network to search for information
in a specific context and without regard to the structure of
the format in which the information is stored.
It is a still further principal object of the present
invention to provide apparatus and methods that enable
operators of primary and secondary servers of an interactive

CA 0220926~ 1997-06-27
" ' ,,

computer network to subscribe with a URL hub without
allowing the URL hub to have unfettered access the
information stored on the server.
It is a still further principal object of the present
invention to provide apparatus and methods that enable
operators of primary and secondary servers of an interactive
computer network to identify and collect information
indicative of the specific characteristics of the
information stored on the server, that was sought by the
visitor to the server.
It is yet another principal object of the present
invention to provide apparatus and methods that enable
operators of primary and secondary servers of an interactive
computer network to more effectively target commercial
advertising that is transmitted through the network.
Additional objects and advantages of the invention will
be set forth in part in the description which follows, and
in part will be obvious from the description, or may be
learned by practice of the invention. The objects and
advantages of the invention may be realized and attained by
means of the instrumentalities and combinations particularly
pointed out in the explanation below.
The present invention includes apparatus configured to
perform a method of collecting data from at least one
searchable data base management system of an interactive
computer network. The computer network includes servers,
routers, and associated searchable data base management
systems that are operated by the servers and accessible via
the routers. Moreover, the interactive computer network is
configured to be accessible via a viewer that is running on
a first computer that functions as a client user
workstation. As noted above, the viewer is a computer
program of a type that is also known as a browser such as

_ CA 0220926~ 1997-06-27 f


Netscape's NAVIGATOR~ browser or Microsoft's EXPLORER~
browser.
To achieve the objects and in accordance with the
purpose of the invention, as embodied and broadly described
herein, the apparatus and method of the present invention
guides the client's search for desired information that is
available on a computer network. The present invention
organizes the information that is available on the network,
into as many central themes as are desired to characterize
the available information. For example, each central theme
may be a real estate listing or a product such as an auto, a
refrigerator, or any other product that can be imagined.
The central theme also could be a service such as dentistry,
photography or any other service that can be imagined.
Then for each central theme, the present invention
defines categories that revolve around that central theme.
The categories will vary depending on the central theme.
However, each category will fall within one of several types
of categories. There is a Single type of category, which
has only one possible category value. There is a Range type
of category, which has two possible category values, one at
each end of the range. There is a StaticList type of
category, which has an open-ended number of possible
category values that are non-volatile (explained more fully
below). There is a DynamicList type of category, which has
an open-ended number of possible category values that are
volatile (explained more fully below).
The present invention then allows the client to define
the search request with greater specificity within each
category. The present invention accomplishes this by
prompting the client to _hoose from a list of available
selections within that category. Thus, the present

CA 0220926~ 1997-06-27


invention urges the client's search request to be formulated
from the selections that are available for each category in
the data base. As the client fills out a search request by
choosing particular selections within each category, these
particular selections combine to produce a sharply focused
search request.
The present invention keeps track of the locations of
information that fit each central theme. At each of these
locations, the present invention can access the categories
and identify information that matches the selections chosen
by the client for each such category. Based on these
matches, the present invention facilitates the client's
inspection of the matching information.
According to the present invention, the information
available at each location on the network is constantly
updated in terms of the available themes and categories.
In accordance with the present invention, a user
interface agent is provided. A user interface agent is a
computer program that can be stored on a computer that is
functioning as a server in a network environment. The user
interface agent is configured to receive from a viewer, a
start signal. For example, a JAVA applet would be
considered a type of user interface agent that can
communicate between a server and the client workstation.
Such JAVA applet would perform such communication via a
router. As embodied herein, each router has been configured
as a JAVA application.
The user interface agent is configured so that when it
opens, it performs the job of making appropriate requests of
the primary router to obtain the information needed to
assist the client user in formulating a search request that
is structured within the available categories. Accordingly,

CA 0220926~ 1997-06-27
,.i. .

when the user interface agent~opens, it performs the TYP
Request, the CAT Request, and the HUB Request. The primary
router responds to the TYP Request, the CAT Request, and the
HUB Request, by providing respectively to the user interface
agent, the TYP Response, the CAT Response, and the ~3
Response. The user interface agent also performs the VAL
Request directed to the primary server. The primary router
also responds to the VAL Request by providing the VAL
Response from the primary DBMS to the user interface agent.
The user interface agent then cedes control to the client
user to allow the client user to define the scope of the
search by selecting either the local mode or the global
mode.
When the client user selects the local mode, the user
1~ interface agent is configured to allow the client user to
build the user's search request. The user interface agent
is configured to allow the client user to choose selections
from among the selections that populate each of the
categories specified by the primary router in the CAT
Response. Once the client user has built a desired search
request, the user interface agent is configured to allow the
client user to initiate the search. Then the user interface
agent is configured to send a LST Request to the primary
router, which collects all of the matching records from the
primary DBMS and returns the matching records to the user
interface agent in the form of a LST Response from which the
user interface agent populates the Result Window. The user
interface agent is further configured to send a request for
more information than is contained in the matching record.
This request is sent in the form of a HOM Request to the
primary router, which is configured to create a HOM Response
and return it to the user interface agent, in order to
permit the client user to view more information than is
provided in the matching record.

CA 0220926~ 1997-06-27
,'

When the client user selects the global mode, the user
interface agent is configured to send a VAL Request via the
primary router to the Hub router and the Hub server. The
Hub router collects the sélections from the Hub DBMS, which
stores the selections from the secondary DBMS's, and returns
the selections to the user interface agent via the primary
router in a HU~3 Response from which the user interface agent
populates the DynamicList and StaticList Categories. As in
the case of the local search, the user interface agent
allows the client user to build the search request and
execute the search. Based on the search criteria selected
by the client user, the user interface agent is configured
to request advertising or other targeted messaging
information, by issuing an ADV Request to the Hub router via
the primary router. The requested advertising (or other
targeted messaging information) is collected and returned by
the Hub router in an ADV Response to the user interface
agent via the primary router. The user interface agent is
further configured to request in a PRO Request directed to
the Hub router via the primary router, the URL for each
server associated with a DBMS that possibly maintains
listings applicable to the client user's search request.
The Hub router is configured to select such URL's from the
profile list of the Hub DBMS and return the matching URL's
in a PRO Response to the user interface agent via the
primary router. The user interface agent is configured to
make a LST Request via the primary router to each URL
returned in the PRO Response. The secondary router resident
at each such URL, collects the matching records that satisfy
the search request in the LST Request and returns such
matching records to the user interface agent via the primary
router in a LST Response, from which the user interface
agent populates the Result Window. The user interface agent
is further configured to send via the primary router a

CA 0220926~ 1997-06-27


request for more information than is contained in the
matching record. This request is sent in the form of a HOM
Request directed to the secondary router that collected the
matching record of particular interest. The secondary
router is configured to create a HOM Response and return it
via the primary router to the user interface agent, in order
to permit the client user to view more information than is
provided in the matching record.
The router for each primary/secondary server is
configured to periodically update its profile stored on the
Hub DBMS. This is be done by periodically sending a COL
Request to the Hub router via the primary router.
The accompanying drawings, which are incorporated in
and constitute a part of this specification, illustrate one
embodiment of the invention and, together with the
description, serve to explain the principles of the
nventlon .
BRIEF DESCRIPTION OF THE DRAWINGS
Fig. 1 is a schematic representation of conventional
apparatus and method for retrieving information via the
Internet;
Fig. 2 is a schematic representation of apparatus and
method according to a presently preferred embodiment of the
present invention;
Fig. 3 is a schematic representation of apparatus and
method according to a presently preferred embodiment of the
present invention configured in the global mode of
operation;
Fig. 4 is a GUI screen of the present invention showing
a HOMESEEK~ Web (HTML) Page from a primary server that has
been accessed by the NETSCAPE~ browseri
Fig. 5 is a GUI screen of the present invention in a
configuration in which control has been ceded to the client

CA 0220926~ 1997-06-27


user to choose from the selections returned in the VAL
Response to create a search request for a data base
management system having information about motor vehicles;
Fig. 6 is a GUI screen of the present invention showing
matching records returned in the LST Response, which
matching records only have in common the Chevrolet Make, out
of the following seven categories used to structure the
information involving motor vehicles: AutoType, Make, Model,
Year, MilesperGallon, RetailPrice, and SalePrice; and
Fig. 7 is a GUI screen of the present invention showing
an HTML page containing the information in one of matching
records retrieved from a search.
DETAILED DESCRIPTION OF THE PREFERRED EMBODIMENTS
Reference now will be made in detail to the presently
preferred embodiments of the invention, one or more examples
of which are illustrated in the accompanying drawings. Each
example is provided by way of explanation of the invention,
not limitation of the invention. In fact, it will be
apparent to those skilled in the art that various
modifications and variations can be made in the present
invention without departing from the scope or spirit of the
invention. For instance, features illustrated or described
as part of one embodiment, can be used on another embodiment
to yield a still further embodiment. Thus, it is intended
that the present invention cover such modifications and
variations as come within the scope of the appended claims
and their equivalents. The same numerals are assigned to
the same components throughout the drawings and description.
The present invention is intended for an environment
that includes an interactive computer network, which is
indicated generally in Fig. 2 by the designating numeral 18.
Some examples of such network can include a local area
network, a wide area network, the Internet or the World Wide
Web. For purposes of this explanation, the World Wide Web



CA 0220926~ 1997-06-27
~ f

(hereafter Web or WWW) will be chosen as the environment of
a presently preferred embodiment of the invention.
As schematically shown in Fig. 2, the basic hardware
components of the interactive computer network are the
client user workstation, which is designated by the numeral
20 and the network servers, which are variously designated
by the numerals 22 for the primary server, 24 for the Hub
server, 26 for a first secondary server and 28 for another
secondary server.
A typical client user of the interactive computer
network, accesses the network via a viewer running on a
first computer functioning as a client user workstation. As
used herein, a viewer is defined as a computer program
capable of using a protocol format to communicate with a
specific internet protocol address such as a tcp/ip address.
Examples of such protocol formats include the hypertext
transfer protocol (http). As known, a viewer can be
configured to use http to communicate using any of a number
of protocol formats that ride on top of tcp/ip, and examples
of such protocols include FTP, Gopher, Usenet and the like.
Thus, in accordance with the present invention, the client
workstation must be provided with viewer software such as
the NETSCAPE NAVIGATOR~ browser. As shown in Fig. 2 for
example, a browser 30 running on a client workstation 20
would be considered a type of viewer that can communicate
with servers that can translate HTML pages and execute
programs in the genre of a user interface agent (described
below) on the client user workstation.
As explained below and schematically in Fig. 2, one of
the network servers is configured as a Hub server 24 in a
preferred embodiment, and each of the other network servers
is configured as a primary server 22 or a secondary server
26, 28. In order to function as a server in the present
invention, at least certain computer hardware is required in

. CA 0220926~ 1997-06-27 _
. ~ .

the form of Random Access Mem~ry (RAM), a hard disk, a
monitor, and connectivity to the interactive computer
network. As to the latter, a Tl line can provide
connectivity between the server and the network. In some
applications, a bank of modems (a.k.a., a modem bank) could
be used to provide connectivity between client user
workstations and a primary server of the network.
Each type of server of the interactive computer network
of the present invention is configured so as to permit the
searching methodology of the present invention to be
executed. The software that should be provided for each
server configured for the present invention, includes an
operating system with a data source that is Open Data Base
Connection (ODBC) compatible and that recognizes
Transmission Control Protocol Internet Protocol (tcp/ip)
addresses. A suitable operating system for each server of
the present invention is the WINDOWS NT~ platform. A Data
Base Management System (DBMS) is one type of data source
that is ODBC compatible, and a suitable DBMS is provided by
a Microsoft~ SQL server. Each server also must be provided
with network software such as Microsoft~ Internet
Information Server. Optional software for each server could
include E-Mail, Firewall, Web Page/Registration, Internet
Connection SW, Internet Service Provider Registration, and
File Transfer Protocol (FTP) software.
In accordance with the present invention, a user
interface agent is configured to structure the client user's
search request according to predetermined categories that
describe the information in the chosen theme. As embodied
herein, the user interface agent is a program that is
specified in an HTML file that originates from a server of
the interactive computer network. Each primary/secondary
server must be provided with the software that defines a
user interface agent (described below) and the supporting

CA 0220926~ 1997-06-27
__


software for the user interface agent. A presently
preferred embodiment of this software is presented below in
Appendix A.
The present invention presents the client user with one
or more themes that describe generally one or more topics
that might interest the client user. If client user wants
to explore the information available for one of these
themes, then the present invention guides the client user in
the formulation of a search request to identify particular
information within the desired theme. The present invention
automatically performs the task of identifying the Uniform
Resource Locator (URL) of each server that controls a DBMS
containing the requested information. The present invention
then automatically retrieves the information that satisfies
the search request formulated by the client user with the
guidance of the present invention. Thus, the present
invention accomplishes the retrieval of the desired
information without requiring the client user to supply any
such URL.
Each data base management system maintained by a
primary/secondary server, has been configured in accordance
with the present invention so that the DBMS stores its
information according to one or more different themes of
information. For example, a DBMS operated by a Fortune~ 500
manufacturer may contain information relating to the theme
of heating and air conditioning systems. That same DBMS
also may contain information relating to the theme of
elevator systems for skyscrapers. Moreover, the information
pertaining to each such theme is further indexed according
to the present invention into one or more categories of
information. Each category of information describes the
information according to characteristics that are deemed of
interest to potential users of the information. For
example, categories for the heating and air conditioning

13

CA 0220926~ 1997-06-27
. _

theme may include the capacity'of each system described by
the information in the DBMS, the price of each system
described by the information in the DBMS, and the fuel that
powers each system described by the information in the DBMS.
In another example, if the theme is residential real
estate listings, one useful category for characterizing such
information would be the house type (one story, two story or
three story). Another useful category for the real estate
listing theme would be the price range of the listed
property. Yet another useful category for the consumer
interested in a real estate theme would be the square
footage of the residence on the listed property. Other
categories could be used, depending upon the perceived
desires of the client users deemed likely to be interested
in the particular theme.
In accordance with the present invention, the data base
management system of each primary/secondary server on the
network, is configured to maintain an initialization file.
The initialization file contains an initialization list.
The initialization list specifies each theme that
characterizes the information that is maintained on the
server~s DBMS and that is available to be searched by users
of the network. The initialization list also specifies
information for accessing the server's DBMS and the URL of
the Hub server.
In accordance with the present invention, a cross-
reference file is maintained in a manner that is accessible
by each primary/secondary server. In a preferred embodiment
of the present invention, the cross-reference file is
maintained on each primary/secondary server. The cross-
reference file contains a category list that includes at
least one category that structures at least some portion of
the information stored on the DBMS operated by the
primary/secondary server. The category list contains each

14

CA 0220926~ 1997-06-27


category of information that is maintained on the server's
DBMS and that the owner of the DBMS desires to make
available to users of the network. For example, consider
the case of the owner of a DBMS that contains information
about real estate listings. In accordance with the present
invention, that real estate listing information is
structured according to categories. Such categories can
include for example, the location of the property that is
the subject of the listing, the asking price for the
property, the type of building on the property (l-story, 2-
story), and the number (e.g., one, two, three, four, five)
of bedrooms in the building. The categories are preselected
to limit their number and to ensure their relevance to
consumers who might be interested in the information.
The cross-reference file further contains for each
category at least such supporting information as the
category header for the user to identify the category, the
DBMS column for each category, the maximum length of a
category value, and the category type. The category type
must be one of at least a Single type, a Range type, a
StaticList type, or a DynamicList type. A separate object
is available to define the attributes of each of the
possible types of categories. As known, an object is an
entity, such as an element in a computer program, that has
its own functionality and is provided with a standard set of
public interfaces so that the object can interact with other
objects that are not familiar with the particulars of how
the object functions. The object has attributes in the form
of data. The object also has attributes in the form of
actions by which the object operates on data.
In accordance with the present invention, once a
category type is assigned to a particular category, then the
appropriate one of the four possible objects for a category
type, is implemented for that category. An attribute of the

CA 0220926~ 1997-06-27 ~

object for each category of the Single type, is that it can
contain only one possible category value. Similarly, each
category of the Range type can contain two possible category
values, one at each end of the range. Each category of the
StaticList type can contain any number of nonvolatile data
selections. What is meant by nonvolatile is that the data
is not likely to be subject to change. Thus, efficiency can
be obtained by storing nonvolatile data in memory so that
such data need not be retrieved from the DBMS as frequently
as volatile data. The values that satisfy the StaticList
type can be drawn from an open-ended number of possible
category values. Each category of the DynamicList type has
data selections that are volatile, which means that the data
is likely to change frequently. The values that satisfy the
DynamicList type also can be drawn from an open-ended number
of possible category values.
In accordance with the present invention, and as noted
above, an additional computer is provided and configured as
a server to function as a URL Hub for the interactive
computer network. In one sense, this so-called Hub server
is the central server of the interactive computer network of
the present invention. As schematically shown in Fig. 3,
the Hub server 24 is configured to control access to a
searchable Hub data base management system, which is
designated by the numeral 32.
The Hub data base management system 32 is operated and
controlled by the Hub server 24 and is configured to contain
a profile list. This profile list is configured to specify
for each primary/secondary DBMS in the network, each theme
that character zes the information that is maintained on
such DBMS and that is to be made available to users of the
network. The profile list is configured further to contain
for each theme, each category of information that is


16

CA 0220926~ 1997-06-27
', :

maintained on each DBMS operated by an additional computer
functioning in the network as a primary/secondary server.
In accordance with the present invention, the user
interface agent is configured to assist the client user to
formulate a search request in terms of at least one category
that characterizes the information available to the client
user from a DBMS in which the information is stored. The
user interface agent might be a JAVA applet, an ActiveX
component or a NetScape~ plug-in. In the presently
preferred embodiment of the invention, a JAVA applet has
been chosen for the user interface agent. A JAVA applet was
chosen for the user interface agent because of
considerations of security, viewer compatibility, and
platform independence. As to security, the JAVA applet is
limited as to what it can access. For example, the JAVA
applet cannot make a socket connection to any server other
than the server from which the JAVA originated (its primary
server); cannot access the client workstation; and cannot
access certain properties of the client workstation. As to
viewer compatibility, a JAVA applet is one of the
technologies that can be executed by a viewer. As to
platform independence, a JAVA applet can be run on the
primary server, which can be running any one of a large
number of the possible platforms that are supported by JAVA.
The HTML file that specifies the user interface agent,
originates from a server that functions as the primary
server during that particular session on the interactive
computer network. Since any server (other than the Hub
server) in the interactive computer network of the present
invention, might be called upon to function as the primary
server in any given session on the network, each server on
the network must be configured with an HTML file that
contains the user interface agent. As schematically shown
in Fig. 2 for example, a user interface agent in the form of

CA 0220926~ 1997-06-27


a Search Applet 34 has been down-loaded from the Primary
Server and run on the Client Workstation. Search Applet 34
is stored on the Primary Web Server 22, which is configured
so that activation of the present invention causes the user
interface agent to be down-loaded from the Primary Server 22
to the Client Workstation 20. The primary server operates a
searchable data base management system, which becomes the
primary DBMS during that session on the network.
In accordance with the present invention, all tcp/ip
communication with the user interface agent, which is
running on the client workstation during a particular
session on the interactive computer network, is processed by
and through a primary router that is configured to run on
the primary server. The user interface agent is configured
to communicate with the primary router via a socket
connection through a port other than the port (typically
denoted 80) used by the primary router's web server to
remain connected to the Web. In a presently preferred
embodiment, the user interface agent uses the port of the
primary server denoted 7777 for the purpose of communicating
with the primary router. In this way, the owner/operator of
the server functioning as the primary server during a
particular session on the network, is assured that the user
interface agent lacks direct access to the primary data base
management system. In accordance with the present
invention, only the primary router, which is running on the
primary server, is permitted such direct access to the
primary server.
As embodied herein and schematically indicated in Fig.
2 for example, the primary router 38 (as well as each router
for each server in the network) has been configured as a
JAVA application. In the JAVA language, a viewer cannot
execute a JAVA application. Thus, in the present invention,
and as schematically indicated in Fig. 2 for example, the

18

CA 0220926~ 1997-06-27
~_ ,~

viewer 30 running on the client user's workstation 20 cannot
load and execute the primary router 38. The software
responsible for the primary router is presented below in
Appendix B.
In order to permit the router to make ODBC calls, the
router software must be run on a server that supports ODBC.
An Intel~ platform is one example that supports ODBC. The
server also must have tcp/ip installed. In embodiments
employing a JAVA application as the router, the server also
must have the JAVA application progr~mm;ng interface (API)
installed and a JAVA ODBC API installed. As schematically
indicated in Fig. 2 for example, an ODBC interface 40 is
provided on the primary server 22 in order to permit the
primary router 38 to make ODBC calls.
In further accordance with the present invention, all
communication between the primary server and each additional
computer that is functioning as a secondary server, is also
processed through the primary router that is running on the
primary server. Moreover, as schematically indicated in
Fig. 2 for example, all communication with each secondary
server 26, 28 iS also processed through a secondary router
46, 4 8, respectively running on the secondary server 26, 28.
The software responsible for the secondary router is
presented below in Appendix B. As schematically indicated
in Fig. 2 for example, an ODBC interface 50, 52 iS provided
respectively on each secondary server 26, 28 in order to
permit the respective secondary router 46, 48 to make ODBC
calls.
In still further accordance with the present invention,
and as schematically shown in Figs. 2 and 3 for example, all
communication with the Hub server 24 iS processed through a
Hub router 44 running on the Hub server. The software
responsible for the Hub router is presented below in
Appendix B. As schematically indicated in Fig. 2 for

19

CA 0220926~ 1997-06-27
'

example, an ODBC interface 54 ls provided on Hub server 24
in order to permit the Hub router 44 to make ODBC calls.
Moreover, as schematically shown in Fig. 2 for example, all
communication between the Hub server 24 and the primary
server 22 is also processed through the primary router 38
that is running on the primary server.
In accordance with the present invention, a number of
different requests and associated responses are employed.
Each of these is explained more fully below. The present
invention employs a Backus-Naur Form (BNF) specification,
which is meta syntactic notation that is used to specify the
syntax of programming language, command sets, and the like.
Both the user interface agent and each router are composed
in accordance with the BNF specification to define each
Request and each associated Response. The BNF specification
defines the basic elements that are used to build each
Request and each Response. The BNF specification also
defines how to combine these basic elements to form each
Request and each Response. In the following presently
preferred embodiment of the BNF specification, all strings
are handled in a case-insensitive manner.

Request Header Structure
rq_hdr~ rq_dest>~rq_str>~rq_id>
rq_dest::=~url_record>" "
rq_str::=["RQ"¦"RHn]","
rq_id::=~4-digit ASCII-decimal number>","

Request Definitions (Coming from applet to router)
request~ rq_hdr>~rq_body>
rq_body::=~category_request>l~value_request>¦<listing_reques
t~l~
profil~_request>l~hub_request>l~product_type_request>¦<
individual_listing_request>l<collection_request>¦<



CA 0220926~ 1997-06-27


ad_request>

category_request::="cat"
value_request::="val" n ~ ~ { cproduct type>","}
[ccat_list>¦"all"]
listing_request::="lst"",ncsearch_rq_list>
profile_request::="pro"","cproduct type>","csearch_rq_list>
hub_request::="hub"
product type_request::="typ"
individual_listing_request::="hom"","~Unique Listing
Identifier~
collection_request::="col"","~url_record>","~product
type>","ccatvalue_list>
ad_request::="adv"","cproduct type>","~search_rq_list>

Response Definitions (Returned from the router to the user
interface agent)
response::=crs_hdr>~rs_body>
rs_hdr::=crs_str>crq_id>
rs_str::="RS"","
rs_body:=ccategory_response>¦cvalue_response>¦clisting_respo
20 . nse>¦
cprofile_response>¦chub_response>¦cproduct_type_response>¦c

individual_listing_response>¦cerr_response>¦ccollection_
response>l~ad_response>

category_response::="cat~ ccattype_rs_list>
value_response::="val"","ccatvalue_list>
listing_response::="lst"",~clisting_rs_list>
profile_response::="pro~","curl_rs_list>
hub_response::="hub~ ,"[curl_record>¦~none~]
product_type_response::="typ~ cproduct type>
individual_list_response::="hom"",~'[curl_record>]

CA 0220926~ 1997-06-27
' ;.,~

err_response::="err~ error_~ecord>
collection_response::="col"",""updated"¦"created"
ad_response::="adv"" "~ad_rs_list~

List Definitions
cat_list::=~category_name>{"l"~categoryname>}O n"
search_rq_list::=~catvalue_list>
catvalue_list::=<category_name>"="~value_list>{"l"ccategory_
name~
~ <value_liSt~}O .n
cattype_rs_list::=<category_record~{~¦''<category_record~}O

value_list::=[<value~{<tab~value>}O n" I "]
listing_rs_list::=~listing_record>{"¦¦"~listing_record>}O n
url_rs_list::=<url_record>{'~ url record~}O n
ad_rs_list::-~ad_record~{''l~<ad_record~}O n

Record De~initions
listing_record::=~catvalue_list>
url_record::=<scheme>"://"<hostname>{":"<port>} {"/"<path>}
error_record::=<3-digitASCII-numeric number~"¦"<Error
message>
category_record::=<category_name><tab><category_header><tab>
<




length><tab><category_datatype>
ad_record::=<ad_description~<tab><url_record>

Other
category_name::=letter{letterldigit¦punc}O n
category_datatype::="Single"¦~Range~¦"DynamicList"¦"StaticLi
st"
value::=[token¦token"-"token]

In accordance with the present invention when the user
interface agent sends a Request to a router the responding

CA 0220926~ 1997-06-27


router will either: a) return a corresponding Response to
the user interface agent, or b) return an error response.
In accordance with the present invention, each Request
from the user interface agent is issued via the primary
router and is configured with the following format (anything
surrounded within the square brackets is optional):
[<Routing Tag~-~RQ,~4-digit unique ID>,<Request Type>[,Data]
In a search conducted in the global mode (described below)
of the present invention, the Routing Tag will be the URL
(including the port) of the server from which the user
interface agent is requesting information. The primary
router is configured to use this tag to route the Request to
the appropriate destination. The primary router is
configured to strip the routing tag from the Request before
the Request is forwarded to the Request's final destination.
In the local mode (described below) of operation, the
primary router does not require a routing tag. The 4-digit
unique ID will be an identifier that is defined by the user
interface agent and included as part of the header of any
Request that the user interface agent sends to the primary
router.
The primary router is configured so that the Response
that the primary router returns to answer the Request,
includes the ID as part of the Response to the Request. For
example, the primary router can be configured to format the
Response to each Request in the following manner:
RS,<4-digit unique ID>,<Response Type>,<Data>
If the router encounters a problem interpreting the Request,
or if the router is unable to formulate a correct Response,
the router is configured to return an error response to the
user interface agent. For example, t~e router can be
configured to format the error response as follows:
RS,<4-digit unique ID>,err,<3-digit error number>¦<Error
Message>

CA 0220926~ 1997-06-27


A potential client user of the present invention is a
person who is using a viewer running on a workstation. The
viewer has retrieved an HTML page, and the monitor of the
workstation contains a display of the HTML page such as
depicted in Fig. 5. It is likely that this HTML page
pertains to a general interest of the potential client user.
However, the potential client user may have accessed the
particular HTML page in error. In any event, if this HTML
page originates from the DBMS of a primary/secondary server
that is configured to form part of the interactive computer
network of the present invention, then this server is
provided with a user interface agent in accordance with the
present invention. Once the client user's viewer has loaded
an HTML from a DBMS operated by a server that forms part of
the interactive computer network of the present invention,
the user interface agent associated with that server is
automatically activated and begins running on the client
user's workstation. Moreover, that server from which the
user interface agent was loaded, becomes the primary server
during that particular session on the network. This
condition is schematically shown in Fig. 2 for example, in
which the client user's browser has loaded an HTML from a
DBMS operated by the Primary Web Server that forms part of
the interactive computer network of the present invention,
and the user interface agent in the form of a Search Applet
associated with that Primary Web Server is automatically
activated and begins running on the client user's
workstation.
As explained more fully below, when the user interface
agent opens, the user interface agent must determine the
location of the searchable information and determine how
that information is characterized. In the present
invention, the user interface agent prepares to make these
determinations by sending to the primary router, the TYP

24

CA 0220926~ 1997-06-27
_ .,

Request, the CAT Request, and'the HUB Request. The primary
router responds to the TYP Request, the CAT Request, and the
HUB Request, by providing, respectively, to the user
interface agent, the TYP Response, the CAT Response, and the
HUB Resp~nse. Then the user interface agent begins
assisting the client user to formulate a search request. In
assisting the client user to formulate a search request, the
user interface agent initially sends the VAL Request to the
primary router. The primary router responds to the VAL
Request by providing the VAL Response from the primary DBMS
to the user interface agent.
As noted above, each server that has information
available to be searched by client users on its associated
DBMS, has been configured according to the present
invention, to structure the information according to broad
themes of information. For example, Fig. 4 depicts a
HOMESEEK~ Web (HTML) Page from a primary server that has
been accessed by the NETSCAPE~ browser. The client user in
this example may have been interested in real estate
listings and may have supplied the browser with a Uniform
Resource Locator (URL) of a particular Web Page. The
browser retrieved this Web Page and displayed it on the
monitor of the client user's workstation. In this
particular example, the information that is available to the
client user for searching on this primary server's DBMS, is
divided into two themes. With this Web Page displayed as
shown in Fig. 4 on the monitor of the client user's
workstation, the client user is presented with two links.
These two links appear as two picture blocks. Each of these
links pertains to one of the two themes of information on
this primary server's DBMS. As can be seen in the example
shown in Fig. 4, one theme is information about homes, and
the other theme is information about products other than
homes.



CA 0220926~ 1997-06-27


The presentation of theseitwo themes is the result of
one of the initial procedures performed by the user
interface agent. When the user interface agent first opens,
the user interface agent has not been provided with the
themes that the primary server can make available to the
client user. Therefore, when the user interface agent first
opens, the user interface agent is configured to begin the
search protocol by requesting the primary router to specify
each theme that the primary server will make available on
the primary data base management system. It is information
in one of these themes for which the present invention will
assist the client user to structure the search to be run by
the client user. As noted above, this theme request that is
issued by the user interface agent to the primary router is
a termed a TYP Request. An example of a TYP Request is:
http://basx.usconnect.com~RQ,OOOl,typ
In this example of a TYP Request, the header is RQ,OOOl,typ,
and the user interface agent is configured to define the
header portion of the TYP Request.
In accordance with the present invention, the primary
router is configured so that when the primary router
receives the TYP Request from the user interface agent, the
primary router parses the TYP Request and retrieves from the
initialization file associated with the primary server, the
information satisfying the TYP Request. The primary router
formats the information satisfying the TYP Request, into a
TYP Response, which identifies each theme in which a search
can be conducted by the user interface agent on the primary
DBMS.
An example of a TYP Response from a primary router that
has been configured to make available real estate listings
(the theme of this data base management system chosen by the
client user) from its data base management system is:
http://basx.usconnect.com~RQ,OOOl,typ,l

26

CA 0220926~ 1997-06-27
!

In accordance with the present invention, the available
themes are provided to the client user via the viewer, which
has accessed a primary server that has returned an HTML such
as shown in Fig. 4. The client user can select one of the
themes by clicking on the link, which is presented as a
picture block. For example, in the embodiment shown in Fig.
4, the primary server returned two themes to the viewer.
One theme is indicated by the picture block labeled "Search
for a Home," and the other theme is indicated by the picture
block labeled "Search for Other Products." The client user
can use the present invention by clicking on (selecting)
either the picture block labeled "Search for a Home" or the
picture block labeled "Search for Other Products." By so
doing, the client user makes an initial choice of the theme
of the search that is to be conducted.
After this selection of one of the available themes is
made, the present invention guides the client user's
formulation of a search request. Initially, the present
invention ensures that the search request for the theme
chosen by the client user, is framed in terms of the
categories that define and characterize the information that
is available to be searched by the client user in the
selected theme. Accordingly, once the user interface agent
has been provided with the theme of the search, the user
interface agent must be provided with the categories that
are pertinent to that theme.
As noted above, the primary DBMS maintained by the
primary server, has been configured in accordance with the
present invention so that the primary DBMS stores its
information according to a number of different categories of
information. When the user interface agent first opens, the
user interface agent has not been provided with the
categories that the primary server can make available for
the purpose of enabling the client user to specify criteria

CA 0220926~ 1997-06-27
!

for a search query of the DBM~ maintained by the primary
server. Therefore, the user interface agent is configured
to begin the search protocol by requesting the primary
router to specify each category that the primary server will
make available from the primary DBMS to structure the search
to be run by the client user. This category request that is
issued by the user interface agent to the primary router is
termed a CAT Request and is specified in the BNF presented
above. An example of a CAT Request made during the local
mode of conducting a search is:
RQ,OOOl,cat
An example of a CAT Request made during the global mode of
conducting a search is:
http://basx.usconnect.com-RQ,OOOl,cat
In each of the above examples of a CAT Request, the header
is RQ,OOOl,cat, and the user interface agent is configured
to define the header portion of the CAT Request.
In accordance with the present invention, the primary
router is configured so that when the primary router
receives the CAT Request from the user interface agent, the
primary router parses the CAT Request and retrieves from the
cross-reference file associated with the primary server, the
information satisfying the CAT Request. The primary router
formats the information satisfying the CAT Request, into a
CAT Response. As specified in the BNF presented above, the
CAT Response identifies each category on the primary DBMS
that the primary server will make available to the user
interface agent. As specified in the BNF presented above,
the CAT Response formatted by the primary router also
includes for each specified category: the category header,
the maximum length of a category value, and the category
type. The type of each category specified in the CAT
Response is one of the possible types noted above, namely,
StaticList, DynamicList, Single, and Range.

28

CA 0220926~ 1997-06-27


An example of a CAT Response from a primary router that
has been configured to make available real estate listings
(the theme of this data base management system chosen by the
client user) from its data base management system is:
S RS,OOOl,cat,HouseType=StaticList~tab~20ctab>House
Type¦City=DynamicList~tab>20~tab>City¦StreetName=Single~tab>
30<tab>Street Name¦PriceRange=Range<tab>lO~tab>Price Range
In this real estate listing example of a CAT Response, the
header is RS,OOOl,cat, and the user interface agent is
configured to interpret this header. Four categories are
present in this real estate listing example, and they are
termed HouseType, City, StreetName and PriceRange. The
HouseType category is a StaticList type, and as such has
possible values that are preordained by the context of the
category and are of a type that are not likely to change
over time. The HouseType category has a maximum length of
20 and is called by the name "~ouse Type." The City
category is a DynamicList type, and as such has possible
values that are dependent on other attributes of the
category, and as such are likely to change, as well as being
likely to be useful for setting up cross-dependencies. For
example, the city where a real estate listing resides, will
depend on the state. Moreover, if the city is known, then
that also narrows the possible zip codes for the desired
listing. The City category has a maximum length of 20 and
is called by the name "City." The StreetName category is a
Single type, and as such has only one possible value. The
StreetName category has a maximum length of 30 and is called
by the name "Street Name." The PriceRange category is a
Range type, and as such has one possible value at each end
of the range. The PriceRange category has a maximum length
of 10 and is called by the name "Price Range."
The primary router is configured to send the CAT
Response to the user interface agent. The user interface

29

CA 0220926~ 1997-06-27
e ,

agent is configured to receive the CAT Response from the
primary router. For each category in the CAT Response, the
user interface agent is configured to create an object that
corresponds to the type of the category. Since there are
four possible types of categories, the user interface agent
is configured to instantiate one of four objects for each
category type in the CAT Response.
As noted above, when the user interface agent first
opens, the user interface agent is configured to request the
primary router to specify the URL of the Hub server. This
request for the Hub server's URL is termed a HUB Request,
which is specified in the BNF described above. An example
of a HUB Request is:
http://basx~usconnect~com-RQ~oool~hub
In this example of a HUB Request, the header is
RQ,0001,hub, and the user interface agent is configured to
define the header portion of the HUB Request. In this
example of the HUB Request, the routing tag is denoted by:
http://basx.usconnect.com. The primary router is configured
to receive the HUB Request, parse the HUB Request, and
retrieve from the initialization file associated with the
primary server, the information satisfying the HUB Request.
The primary router formats the information satisfying the
HUB Request, into a HUB Response, which identifies the URL
of the Hub server, and returns the HUB Response to the user
interface agent. The format of the HUB Response is
specified in the BNF described above. The HUB Response can
take one of two form, an example of each form being:
RS,0001,hub,http://bduncan:81
-OR-
RS,0001,hub,none
In the first example of a HUB Response, the URL of the Hub
server is bduncan:81. The "none" response in the second
example of the HUB Response, signifies that the primary



_ CA 0220926~ 1997-06-27


router does not know the Hub ~RL, or that the primary router
does not allow global requests.
After the user interface agent receives the categories
in the CAT Response from the primary server, the user
interface agent is configured to request the primary server
to provide selections to be used to populate each StaticList
category and each DynamicList category. This request issued
by the user interface agent to the primary router is a VAL
Request and is specified in the BNF presented above. An
example of a VAL Request made to the primary router of a
primary server that has been configured to make available
real estate listings (the theme of this primary data base
management system chosen by the client user) is:
RQ,0001,val,HouseType¦City
In this real estate listing example of a VAL Request, the
header is RQ,0001,val, and the user interface agent is
configured to define the header. The StaticList category is
HouseType, and the DynamicList category is City.
In accordance with the present invention, the primary
router is configured so that when the primary router
receives the VAL Request from the user interface agent, the
primary router parses the VAL Request and retrieves from the
primary data base management system associated with the
primary server, the information satisfying the VAL Request.
The primary router is configured to format the information
satisfying the VAL Request, into a VAL Response. As
specified in the BNF presented above, the VAL Response
contains all possible selections for each StaticList
category and each DynamicList category passed to the Primary
router in the VAL Request.
An example of a VAL Response from a primary server that
has been configured to make available real estate listings
from its data base management system is:
RS,0001,val,HouseType=One Storyctab>Two Story<tab>ThreeStory

CA 0220926~ 1997-06-27

. .

¦City=Columbia~tab~Lexington<~ab>Cayce~tab>Re~3ank~tab>Pelio
n




In this real estate listing example of a VAL Response, the
header is RS,0001,val, and the user interface agent is
configured to interpret the header. In this example, when
the client user eventually begins formulating a particular
search request, the possible selections that the user
interface agent will make available to the client user in
the HouseType category, which is a StaticList type, are: One
Story, Two Story, and Three Story. Similarly, the possible
selections that the user interface agent will make available
to the client user in the City category, which is a
DynamicList type, are: Columbia, Lexington, Cayce, RedBank
and Pelion.
The primary router is configured to send the VAL
Response to the user interface agent, which is configured to
receive the VAL Response, parse VAL Response, and call a
populate function, which passes a set of values to a
specified object, which in this case is either the
StaticList object created for the HouseType category or the
DynamicList object created for the City category. As known
in the art, a function is a process or action that resides
within a computer program and that is called for a specific
purpose. In this case, the populate function is configured
to fill the specified object with the values returned as the
selections in the VAL Response.
In accordance with the present invention, the user
interface agent is configured to permit the client user to
define the scope of the search by choosing to have the user
interface agent operate in one of two alternative modes. In
a first mode of operation known as the local mode, the user
interface agent is configured to conduct a local search,
which is a search that is restricted to the DBMS operated by
the primary server. In a second mode of operation known as

CA 0220926~ 1997-06-27
~," .,

the global mode, the user interface agent is configured to
conduct a global search, which is a search that is not
restricted to the DBMS of the primary server.
As explained above, when the user interface agent first
opens, the user interface agent immediately and
automatically performs the HUB Request, the TYP Request, the
CAT Request, and the ~AL Request and has been provided with
the HUB Response, the TYP Response, the CAT Response, and
the VAL Response by the primary router. After these
preliminary Requests and Responses have been completed, then
the user interface agent is configured to cede control to
the client user to select whether to conduct a local search
or a global search.
Referring to Fig. 4, for purposes of this explanation,
it is assumed that the client user in this example has
clicked on the picture block labeled "Search for Other
Products" and has been presented with a number of different
themes. Though the menu of other themes is not shown, it is
assumed for purposes of this explanation that the client
user has selected a motor vehicle theme. Moreover, as shown
in Fig. 5, the client user has the option of searching for
information satisfying this motor vehicle theme by choosing
between a local search and a global search. The client user
makes this choice in the Fig. 5 embodiment by either
entering a check in the box next to the heading "Expanded
Search" or leaving that box blank. In the view shown in
Fig. 5, the "Expanded Search?" box has been checked,
indicating that the client user desires to conduct a global
search, which is the second mode of operation of the present
invention. However, for purposes of explaining the local
search mode of operation of the present invention, the
following discussion proceeds on the basis that the client
user has left the ~Expanded Search~ box unchecked, i.e.,
blank. The components and process steps for conducting such

CA 0220926~ 1997-06-27
:

a local search according to a presently preferred embodiment
of the present invention are described first. The global
mode of operation, which is the second or alternative mode
of operation of the present invention, is described
thereafter.
After the user interface agent has determined that the
client user has selected a local search, the user interface
agent is configured to allow the client user to control the
user interface agent to build the user's search request.
The user interface agent is configured to allow the client
user to build a search request by allowing the client user
to choose selections from among the selections that populate
each of the categories specified by the primary router in
the CAT Response. The user interface agent is configured to
cede to the client user, control over the user interface
agent for adding search entries to the client user's search
request by choosing from among the category selections
populating each category.
For example, as shown in Fig. 5, a graphical user
interface (GUI) is depicted of a kind that can be presented
to the client user by an embodiment of the present invention
that the client user has activated via a NETSCAPE~ viewer to
search for information satisfying a motor vehicle theme. In
the GUI screen shown in Fig. 5, the user interface agent has
ceded to the client user, control over the user interface
agent to formulate the client user's search request. In
this particular GUI screen, the information stored in the
primary data base management system satisfies the motor
vehicle theme, and the categories appear under the Menu
Window that is titled "Features." The information stored
under this motor vehicle theme has been characterized by the
following categories: Auto Type, Make, Model, Year, Miles
per Gallon, Retail Price and Sale Price, which are contained
in the category list maintained in the cross-reference file

34

CA 0220926~ 1997-06-27 -
, ,:

of the primary server. These are the categories returned in
the CAT Response to the user interface agent from the cross-
reference file of the DBMS of the primary server. In the
GUI screen shown in Fig. 5, the client user has highlighted
the Make category, which is a StaticList type. In this
example, the only possible selection for this StaticList
category is Chevrolet, which appears in the Menu Window
entitled "Options" in the GUI screen shown in Fig. 5. The
"Options" window contains the display for each highlighted
category. The values appearing in the "Options" window are
the values returned in the VAL Response to the user
interface agent from the DBMS of the primary server. In
this example, the client user has selected "Chevrolet" for
the search request, which appears in the Selection Window
titled "Selected Features" in the GUI screen shown in Fig.
5. Similarly, for each category, the client user selects
from among the values in the "Options" window, and each
value selected by the client user, appears in the "Selected
Features" window. The values appearing in the "Selected
Features" window constitute the client user's search request
that the user interface agent has helped formulate by
defining the theme, the categories, and the values available
for each category.
In the preferred embodiment of the present invention,
the user interface agent is configured to cede to the client
user, control over the user interface agent for tailoring
the search request. The user interface agent is configured
to allow the client user to add search entries to the user's
search request by entering one user-desired category value
for each single type category, and to add two user-desired
category values for each range type category. Moreover, the
user interface agent is configured to cede to the client
user, control over the user interface agent for allowing the
client user to delete any number of search entries from the

CA 0220926~ 1997-06-27
! !

user's search request, including the deletion of the entire
search request.
In further accordance with the present invention, the
user interface agent is configured to cede to the client
user, control over the user interface agent for allowing the
client user to initiate the search of the primary DBMS
according to the search request that the client user has
built. In the embodiment shown in Fig. 5 for example, the
client user can initiate the search request that appears in
the Selection Window entitled "Selected Features," by
clicking the button labeled "Search," which is located
immediately to the right of the legend "Expanded Search./'
In still further accordance with the present invention,
when the client user initiates the search request in the
local mode of operation, the user interface agent is
configured to send to the primary router, a request for
information that satisfies the search request specified by
the client user. This request issued by the user interface
agent to the primary router is a LST Request, which has a
format that is specified in the BNF presented above. An
example of a LST Request made to a primary ser~er that has
been configured to make available real estate listings (the
theme of the primary data base management system in this
example) is:
RQ,OOOl,LST,HouseType=TwoStory<tab>ThreeStory¦City=Columbia<
tab>Lexington¦PriceRange=lOOOOO<tab>120000
In this real estate listing example of a LST Request, the
header is RQ,OOOl,LST, and the user interface agent is
configured to define the header. The selections made by the
client user in the HouseType category, which is a StaticList
type, are: TwoStory and ThreeStory. The selections made by
the client user in the City category, which is a DynamicList
type, are: Columbia and Lexington. The entries made by the


36

CA 0220926~ 1997-06-27 -

client user in the PriceRange category, which is a Range
type, are: 100000 and 120000.
In an alternative example shown in Fig. 5, the LST
Request made to a primary server that has been configured to
make available motor vehicles offered for sale (the theme of
this primary data base management system chosen by the
client user upon activating the present invention) is:
RQ,OOOl,LST,Make=Chevrolet
In this motor vehicle example of a LST Request, the header
is RQ,OOOl,LST, and the user interface agent is configured
to define the header. The client user only made a selection
in the Make category, which is a DynamicList type, and chose
Chevrolet from among this one possible selection returned in
the VAL Response.
In accordance with the present invention, the primary
router is configured so that when the primary router
receives the LST Request from the user interface agent, the
primary router is configured to retrieve from the primary
data base management system, each record that satisfies the
LST Request. The Primary router is configured to organize
each record of matching data as a separate row by placing a
double pipe (e.g., ~ ¦ " ) between each matching record. The
primary router is configured to format the information
satisfying the LST Request, into a LST Response, which
includes each matching record in the primary data base
management system. As specified in the BNF presented above,
the LST Response formatted by the primary router includes
for each matching record: a unique identifier and a value
for each category that was specified in the CAT Response.
Thus, each row in the LST Response includes a data element
that uniquely identifies said row on the primary data base
management system and data elements that cumulatively
satisfy each of the categories that were specified in the
CAT Response.

-' CA 0220926~ 1997-06-27 f--

An example of a LST Respo~nse from a primary router that
has been configured to make available real estate listings
(the theme of the data base management system in this
example) from the primary DBMS is:
RS,0OOl,LST,ListNum=960053¦HouseType=2
Story¦City=Lexington¦StreetName=Magnolia
Circle¦PriceRange=llO000 ¦¦ ¦¦ListNum=960167¦HouseType=2
Story¦City=Columbia¦Street Name=Gamecock
Place¦PriceRange=115000
In this real estate listing example of a LST Response, the
header is RS,OOOl,LST, and the router is configured to
define the header. Four categories are present in this real
estate listing example, and they are termed HouseType, City,
StreetName and PriceRange. In the first matching record,
the HouseType category, which is a StaticList type, is
satisfied by a 2 story house, the City category, which is a
DynamicList type, is satisfied by the city of Lexington, the
StreetName category, which is a Single type, is satisfied by
Magnolia Circle, and the PriceRange category, which is a
Range type, is satisfied by 110000. The unique identifier
for the first matching record is 960053. In the second
matching record, the HouseType category is satisfied by a
two story house, the City category is satisfied by the city
of Columbia, the StreetName category is satisfied by
Gamecock Place, and the PriceRange category is satisfied by
115000. The unique identifier for the second matching
record is 960167.
In an alternative example that might accompany the GUI
screen shown in Fig. 6, the highlighted entry and the first
truck entry immediately underneath the highlighted entry, of
the LST Response made from a primary server that has been
configured to make available information about motor
vehicles offered for sale (the theme of this primary data
base management system) is:

38

CA 0220926~ 1997-06-27 -~

RS,OOOl,LST,ListNum=8754887¦AutoType=Car¦Make=Chevrolet¦Mode
l=Lllm; n~ ¦ Year=1994¦MilesperGallon=38¦RetailPrice=26545¦SaleP
rice=24000¦¦¦¦ListNum=0074421¦AutoType=truck¦Make=Chevrolet¦Mo
del=Tahoe¦Year=1996¦MilesperGallon=26¦RetailPrice=52000¦Sale
Price=49999
In this motor vehicle example of a LST Response, the header
is RQ,OOOl,LST. The client user only made a selection in
the Make category, and this did little to limit the scope of
the search. For each search request, the router is
configured to return no more than a predetermined maximum
number of records. For example, the router can be
configured to return no more than 50 records from a server
for a given request. Though as shown in Fig. 6, there would
likely have been a large number of matching records, which
only have in common the Chevrolet Make, only two of the
matching records shown in Fig. 6 are given in the example in
order to save space. In this example, seven categories are
used to structure the information involving motor vehicles,
and the seven categories are termed AutoType, Make, Model,
Year, MilesperGallon, RetailPrice, and SalePrice. In the
highlighted matching record, the AutoType category, which is
a StaticList type, is satisfied by a car, the Make category,
which is a DynamicList type, is satisfied by Chevrolet, the
Model category, which is a DynamicList type, is satisfied by
Lumina, the Year category, which is a Range type, is
satisfied by 1994, the MilesperGallon category, which is a
Range type, is satisfied by 38, the RetailPrice category,
which is a Range type, is satisfied by 26545, and the
SalePrice category, which is a Range type, is satisfied by
24000. In the first truck matching record, the AutoType
category is satisfied by a truck, the Make category is
satisfied by Chevrolet, the Model category is satisfied by
Tahoe, the Year category is satisfied by 1996, the
MilesperGallon category is satisfied by 26, the RetailPrice

39

- CA 0220926~ 1997-06-27 .-

category is satisfied by 52000, and the SalePrice category
is satisfied by 49999.
The primary router is configured to send the LST
Response to the user interface agent. The user interface
agent is configured to receive the LST Response, to clear
out any pre-existing records in the free-floating Result
Window on the client workstation, add a header to the Result
window, and populate the Result Window on the client
workstation with a display of the matching records. For
example, in the GUI screen shown in Fig. 6, the user
interface agent has added the header "Seek & Find Search
Results" to the free-floating Result Window and populated
the Result Window with each of the matching records sent
from a primary server that has been configured to make
available information about motor vehicles offered for sale.
In accordance with the present invention, the user
interface agent is configured to cede to the client user,
control over the user interface to permit the user to scroll
through the matching records that are displayed by the user
interface agent in the Result Window.
In further accordance with the present invention, the
user interface agent is further configured to cede control
to the client user to permit the client user to choose to
view more information than is provided in the matching
record. When the client user chooses to view additional
information for a matching record, the user interface agent
is configured to issue to the primary router, a request to
return the specific URL of an HTML page that contains
additional information than is contained in the matching
record chosen by the client user. This request issued by
the user interface agent to the primary router is a HOM
Request. As specified in the BNF presented above, the HOM
Request contains a unique listing identifier. An example of
a HOM Request is:



-' CA 0220926~ 1997-06-27 ,~

RQ,0001,HOM,95065
In this example of a HOM Request, the header is RQ,0001,HOM
and is defined by the user interface agent. The unique
listing identifier for the matching record in the LST
Response is 95065, which specifies the address of the
matching record in the primary DBMS.
In accordance with the present invention, the primary
router is configured so that when the primary router
receives the HOM Request from the user interface agent, the
primary router parses the HOM Request and is configured to
query the primary data base management system for detailed
information about the specific row specified in the HOM
Request. The primary server is configured to retrieve a
pre-existing HTML file if such HTML file exists. However,
if such HTML file does not exist, the primary server is
configured to build an HTML file from the detailed
information and to save the built HTML file on the primary
server. The primary server is configured to format the
information satisfying the HOM Request, into a HOM Response,
which identifies the URL of the matching record that the
client user has chosen to examine on the primary DBMS. As
specified in the BNF presented above, the HOM Response
contains the Universal Resource Locator of the individual
listing.
An example of a HOM Response from a primary server that
has been configured to make available information about
motor vehicles offered for sale (the theme of the data base
management system in this example) from the primary DBMS is:
RS,0001,HOM,URL=HTTP:/ /176.16.9.12: 80/auto/chevy/html/5.htm
In this motor vehicle example of a HOM Response, the header
is RS, 0001,HOM and is defined by the user interface agent.
The Universal Resource Locator (URL) in this motor vehicle
example is: HTTP://176.16.9.12: 80/auto/chevy/html/5.htm.


41

- CA 0220926~ 1997-06-27 t~

The primary server is configured to send the HOM
Response to the primary router, which is configured to parse
the HOM Response and to send the parsed HOM Response to the
user interface agent. The user interface agent is
configured to receive the HOM Response containing the
specific URL for the matching record chosen for examination
by the client user. The user interface agent is further
configured to instantiate a second viewer and to set this
second viewer location to the specific URL for the matching
record chosen for ~x~m; n~tion by the client user. Fig. 7
depicts the GUI screen that displays from a primary server
that has been configured to make available information about
motor vehicles offered for sale (the theme of the primary
data base management system in this example), the
information in the first one of the matching records
depicted in Fig. 6.
This concludes the description of the present invention
when the user interface agent is configured to operate in
the local mode.
As noted above, the user interface agent is configured
to permit the client user to cause the user interface agent
to operate in a second mode of operation known as the global
mode. In the global mode, the user interface agent is
configured to conduct a global search, which is a search
that is not restricted to the primary server. In conducting
a global search, the user interface agent is configured to
broaden the scope of the search to encompass information
stored on data base management systems controlled by servers
other than the primary server. As shown schematically in
Figs. 2 and 3 for example, each of these other servers is
termed a secondary server during a given session of the
client user on the interactive computer network of the
present invention. The main distinction between the primary
server and each secondary server is that the primary server

42

- CA 0220926~ 1997-06-27 --'

is the server from which the user interface agent originated
during a particular session on the network. Thus, any
server (except the Hub server described below) in the
interactive computer network can function as a primary
server or a secondary server, depending on the origin of the
user interface agent.
As noted above, each secondary server operates a
searchable data base management system (DBMS), which is a
secondary DBMS and is configured to store data in a
structured data format. The structured format of each
secondary DBMS can be the same format as that used for the
primary DBMS, but need not be the same format as that used
for the primary DBMS or for any other secondary DBMS.
As explained above, when the user interface agent
opens, the user interface agent performs the TYP Request,
the CAT Request, and the HUB Request. The primary router
responds to the TYP Request, the CAT Request, and the HUB
Request, by providing to the user interface agent, the TYP
Response, the CAT Response, and the HUB Response. The user
interface agent also performs the VAL Request directed to
the primary server. The primary router also responds to the
VAL Request by providing the VAL Response from the primary
DBMS to the user interface agent. The user interface agent
then cedes control to the client user to allow the client
user to define the scope of the search by selecting either
the local mode or the global mode. In the view shown in
Fig. 5, the client user has chosen the option of using a
global search to find information satisfying this motor
vehicle theme. The client user has made this choice in the
Fig. 5 embodiment by entering a check in the box next to the
heading ~Expanded Searchn rather than leaving that box
blank.
When the client user selects the global mode, the user
interface agent is configured to send a VAL Request to the

43

CA 0220926~ 1997-06-27 ~-'

Hub server to begin the process of populating the
DynamicList and StaticList Categories from the secondary
DBMS's. As shown schematically in Fig. 2 for example, the
user interface agent is configured to request the Hub
router, via the primary router, to provide selections to be
used to populate each StaticList category and each
DynamicList category for each secondary DBMS in the computer
network. This request issued by the user interface agent to
the Hub router via the primary router, is a VAL Request and
is specified in the BNF presented above. An example of a
VAL Request made to the Hub router of a Hub server for
secondary DBMS's that have been configured to make available
real estate listings (the theme of the secondary DBMS's
chosen by the client user) is:
RQ,0OOl,val,HouseType¦City
In this real estate listing example of a VAL Request, the
header is RQ,OOOl,val, and the user interface agent is
configured to define the header. The StaticList category is
HouseType, and the DynamicList category is City.
In accordance with the present invention, the Hub
router is configured so that when the Hub router receives
the VAL Request from the user interface agent via the
primary router, the Hub router parses the VAL Request and
retrieves from the Hub data base management system
associated with the Hub server, the information satisfying
the VAL Request. The Hub router is configured to format the
information satisfying the VAL Request, into a VAL Response.
As specified in the BNF presented above, the VAL Response
contains all possible selections for each StaticList
category and each DynamicList category passed to the Hub
router in the VAL Request.
An example of a VAL Response from a Hub server for
secondary DBMS's that have been configured to make available
real estate listings from their DBMS's is:

44

CA 0220926~ 1997-06-27 !'~-

RS,0001,val,HouseType=OneStory<tab>TwoStory<tab>ThreeStory<t
ab>FourStory¦City=Columbia<tab>Lexington<tab>Cayce<tab>RedBa
nk<tab>Pelion<tab>Dearborn<tab>GrossePoint<tab>Warren<tab>Wi
ndsor<tab>HighlandPark
In this real estate listing example of a VAL Response, the
header is RS,0001,val, and the user interface agent is
configured to interpret the header. In this example, when
the client user eventually begins formulating a particular
search request, the possible selections that the user
interface agent will make available to the client user in
the HouseType category, which is a StaticList type of
category, are: One Story, Two Story, Three Story and Four
Story. Similarly, the possible selections that the user
interface agent will make available to the client user in
the City category, which is a DynamicList type of category,
are: Columbia, Lexington, Cayce, RedBank, Pelion, Dearborn,
Grosse Pointe, Warren, Windsor and Highland Park.
The Hub router is configured to send the VAL Response
to the user interface agent via the primary router. The
user interface agent is configured to receive the VAL
Response, parse the VAL Response, and call a populate
function, which fills the specified object with the values
returned as the selections in the VAL Response. In this
case, the specified object is either the StaticList object
created for the HouseType category or the DynamicList object
created for the City category.
After the user interface agent populates the selections
of the categories that are of the StaticList type and
DynamicList type, the user interface agent is configured to
allow the client user to control the user interface agent to
build the user's search request. The user interface agent
is configured to allow the client user to build a search
request by allowing the client user to choose selections
from among the selections that populate each of the

~ CA 0220926~ 1997-06-27 t~-

categories specified by the Hub router in the CAT Response.
The user interface agent is configured to cede to the client
user, control over the user interface agent for adding
search entries to the client user's search request by
choosing from among the category selections populating each
category. Referring again to Fig. 5 for example, the client
user in this example has double-clicked in a previous screen
to select the picture block labeled "Search for Other
Products" and has selected a motor vehicle theme. As
described above in connection with the local search, the
client user similarly is building a search request, which
appears in the Selection Window labeled "Selected Features,"
by selecting values corresponding to each category returned
in the CAT Response to the user interface agent by the
primary router.
The user interface agent is further configured in
accordance with the present invention, to cede to the user,
control over the user interface agent for allowing the user
to initiate the client user's search request. For example,
in the GUI screen shown in Fig. 5, the client user can
depress the button entitled "Search" in order to initiate
the search request appearing in the Selection Window
entitled nSelected Features."
Once the client user has initiated the search in the
global mode of operation, the user interface agent is
configured to request advertising (or other targeted
messaging information) to be displayed to the client user.
The user interface agent is configured to select such
advertising or other targeted messaging information
according to the search criteria selected by the client
user. In order to request such advertising or other
targeted messaging information, the user interface agent is
configured to issue an ADV Request to the Hub router via the
primary router. The purpose of this ADV Request is to

46

~ CA 0220926~ 1997-06-27 ,-

receive advertising text, graphics and/or sound (or other
targeted messaging informational text, graphics and/or
sound) stored on the Hub data base management system. The
advertising (or other targeted messaging information)
returned by the Hub router to the user interface agent via
the primary router, will be determined by the Hub router
according to the search criteria selected by the client
user. Desirably, the Hub router is configured to limit the
number of ads (or the volume of other targeted messaging
information) returned to the user interface agent, to a
reasonable number, such as five URL's. The ADV Request is
formatted according to the BNF described above. An example
of an ADV Request is:
http://basx.usconnect.com-RQ,OOOl,ADV,HouseType=Two
Story~tab>
ThreeStory¦City=Columbia<tab>Lexington¦PriceRange=lOOOOO<tab
>120000
The Hub router is configured to receive the ADV Request from
the user interface agent, parse the ADV Request, and return
to the user interface agent, the appropriate advertising or
other information. The Hub router is configured to format
an ADV Response containing the appropriate advertising or
other information to be returned to the user interface
agent. The ADV Response is formatted according to the BNF
described above. An example of an ADV Response is:
RS,0001,ADV,The Computer Group - US
Connect<tab>http://teg.usconnect.com
In this motor vehicle real estate listing example of an ADV
Response shown in Fig. 6, the header is RS,OOOl,ADV, and the
user interface agent is configured to interpret the header.
The advertising text is The Computer Group - US Connect.
The URL of the HTML page containing the advertising text is
http://teg.usconnect.com. As shown in Fig. 6, the
advertising text is displayed to the client user in the bar

47

- CA 0220926~ 1997-06-27 ~-

space located near the bottom of the Result Window labeled
"Seek & Find Search Results."
When the user interface agent determines that the
client user has indicated a global search, the user
interface agent is further configured to request the URL for
each server associated with a data base management system
that possibly maintains listings applicable to the search
request formulated by the client user. As noted above, the
Hub DBMS maintains a profile list that contains for each
DBMS on the network, each theme and each category
characterizing the information on such DBMS that is to be
made available to client users of the newtork. As
schematically indicated in Fig. 2 for example, the user
interface agent is configured to request such URL's from the
Hub router via the primary router. The Hub router is
configured to select such URL's according to the client
user's search request. In order to request such URL's, the
user interface agent is configured to issue a PR0 Request to
the Hub router via the primary router. Desirably, the Hub
router is configured to limit the number of URL's returned
to the user interface agent, to a reasonable number, such as
five. The PRO Request is formatted according to the BNF
described above. An example of an PR0 Request is:
http://basx.usconnect.com~RQ,OOOl,PRO,HouseType=TwoStory<tab
>ThreeStory¦City=Columbia<tab>Lexington¦PriceRange=lOOOOO~ta
b>120000
The Hub router is configured to receive the PR0 Request
from the user interface agent via the primary router and to
parse the PRO Request. The Hub router is configured to
compare the search request to the profile list maintained on
the Hub DBMS. The Hub router is configured to select URL's
that are listed as having data matching the criteria
specified in the search request. The Hub router is
conrigured to format a PRO Response containing the

48

-- CA 0220926~ 1997-06-27 ~-'

appropriate URL's to be returned to the user interface
agent. The Hub router is configured to return the
appropriate URL's to the user interface agent via the
primary router. The PRO Response is formatted according to
the BNF described above. An example of a PRO Response is:
RS,OOOl,PRO,http://mls.detroit.com:7777¦http://mis.seattle.c
om:7777¦http://mls.miami.com:7777
In this real estate listing example of a PRO Response, the
header is RS,OOOl,PRO, and the user interface agent is
configured to interpret the header. The URL's for the
servers associated with DBMS's that have been selected as
possibly having information satisfying the search request
formulated by the client user are:
http://mls.detroit.com:7777; http://mis.seattle.com:7777,
and http://mls.miami.com:7777.
The primary router is configured to receive the PRO
Response, parse the PRO Response, and provide the PRO
Response to the user interface agent.
In accordance with the present invention, the user
interface agent is configured to create server objects for
each URL returned in the PRO Response. However, because of
the manner in which the Hub router is configured to select
URL's responsive to the PRO Request, it is possible that not
each DBMS associated with a server identified by a URL
returned in the PRO Response, will definitely have a record
that satisfies all of the search criteria of the search
request. For example, the server identified by the URL
http://mls.miami.com:7777 might have listings for houses
satisfying the "Two Storyn selection in the HouseType
category, and listings for houses satisfying the ~Columbia~
selection in the City category. Although the Hub router is
configured to determine the applicability of each category,
the Hub router is not configured to cross-reference
information between any two categories. Thus, in the

49

-' CA 0220926~ 1997-06-27 iJ -

example given, the Hub router is not configured to select
only those servers associated with a DBMS having information
satisfying both "Two Story" for the HouseType category and
"Columbia" for the City category.
In this global mode of operation, the user interface
agent is configured to use the search request built by the
cllent user to search simultaneously, each DBMS maintained
by a server returned in the PRO Response to the user
interface agent by the Hub server. The user interface agent
is further configured to use the LST Request to
simultaneously query each such primary server and secondary
server for HTML pages that match all of the search criteria
in the client user's search request. In further accordance
with the present invention, when the client user initiates
the search request, the user interface agent is configured
to send to the primary router, a request for information
that satisfies the search request specified by the client
user. This request issued by the user interface agent to
the primary router is a LST Request, which has a format that
is specified in the BNF presented above. An example of a
LST Request made during a global search to a server (primary
or secondary) that has been configured to make available
real estate listings (the theme of the DBMS in this example)
lS:
http://basx.usconnect.com-RQ,OOOl,LST,HouseType=TwoStory<tab
>




ThreeStory¦City=Columbia<tab>Lexington¦PriceRange=lOOOOO<tab
>




120000
In an alternative example shown in Fig. 5, the LST
Request made during a global search to a server that has
been configured to make available motor vehicles offered for
sale (the theme of this data base management system chosen




- CA 0220926~ 1997-06-27 j~

by the client user upon activa~ting the present invention)
i s :
http://basx usconnect.com-RQ,OOOl,LST,Make=Chevrolet
In accordance with the present invention, each
secondary router is configured so that when the secondary
router receives the LST Request from the user interface
agent via the primary router in the global mode of
operation, the secondary router is configured to retrieve
from the secondary data base management system, each record
that satisfies the LST Request. The secondary router is
configured to organize each record of matching data as a
separate row by placing a double pipe (e.g., " ~ ) between
each matching record. The secondary router is configured to
format the information satsifying the LST Request, into a
LST Response, which includes each matching record in the
secondary data base management system. As specified in the
BNF presented above, the LST Response formatted by the
secondary router includes for each matching record: a unique
identifier and a value for each category that was specified
in the CAT Response. Thus, each row in the LST Response
includes a data element that uniquely identifies said row on
the secondary data base management system and data elements
that cumulatively satisfy each of the categories that were
specified in the CAT Response.
2 5 An example of a LST Response from a secondary router
that has been configured to make available real estate
listings (the theme of the data base management system in
this example) from the secondary DBMS is:
RS,OOOl,LST,ListNum=960053¦HouseType=2
Story¦City=Lexington¦StreetName=Magnolia
Circle¦PriceRange=l10 ooo ¦¦ ¦¦ ListNum=960167¦HouseType=2
Story¦City=Columbia¦Street Name=Gamecock
Place¦PriceRange=115000

- CA 0220926~ 1997-06-27 -

In this real estate listing example of a LST Response, the
header is RS,OOOl,LST, and the router is configured to
define the header. Four categories are present in this real
estate listing example, and they are termed HouseType, City,
StreetName and PriceRange. In the first matching record,
the HouseType category, which is a StaticList type, is
satisfied by a 2 story house, the City category, which is a
DynamicList type, is satisfied by the city of Lexington, the
StreetName category, which is a Single type, is satisfied by
Magnolia Circle, and the PriceRange category, which is a
Range type, is satisfied by 110000. The unique identifier
for the first matching record is 960053. In the second
matching record, the HouseType category is satisfied by a
two story house, the City category is satisfied by the city
of Columbia, the StreetName category is satisfied by
Gamecock Place, and the PriceRange category is satisfied by
115000. The unique identifier for the second matching
record is 960167.
In an alternative example that might accompany the GUI
screen shown in Fig. 7, the first two entries of an LST
Response made from a secondary server that has been
configured to make available information about motor
vehicles offered for sale (the theme of this secondary data
base management system) are:
RS,OOOl,LST,ListNum=8754887¦AutoType=Car¦Make=Chevrolet¦Mode
l=Geo¦Year=1996¦MilesperGallon=45¦RetailPrice=8930¦SalePrice
=870 0 ¦¦ ¦¦ ListNum=0074421¦AutoType=car¦Make=Chevrolet¦Model=Geo
¦Year=1995¦MilesperGallon=45¦RetailPrice=7000¦SalePrice=6500
In this motor vehicle example of the first two entries of a
LST Response, the header is RQ,OOOl,LST. The client user
only made a selection in the Make category, and this did
little to limit the scope of the search. For each search
request, the secondary router is configured to return no
more than a predetermined maximum number of records. For

52

-'- CA 0220926~ 1997-06-27 .~

example, the secondary router can be configured to return no
more than 50 records from a server for a given request.
Though as shown in Fig. 6, there would likely have been a
large number of matching records, which only have in common
the Chevrolet Make, only the first two of the matching
records shown in Fig. 6 are given in the above example in
order to save space. In this example, seven categories are
used to structure the information involving motor vehicles,
and the seven categories are termed AutoType, Make, Model,
Year, MilesperGallon, RetailPrice, and SalePrice. In the
first matching record, the AutoType category, which is a
StaticList type, is satisfied by a car, the Make category,
which is a DynamicList type, is satisfied by Chevrolet, the
Model category, which is a DynamicList type, is satisfied by
Geo, the Year category, which is a Range type, is satisfied
by 1996, the MilesperGallon category, which is a Range type,
is satisfied by 45, the RetailPrice category, which is a
Range type, is satisfied by 8930, and the SalePrice
category, which is a Range type, is satisfied by 8700. The
unique identifier for the first matching record is 9754887.
In the second matching record, the AutoType category is
satisfied by a car, the Make category is satisfied by
Chevrolet, the Model category is satisfied by Geo, the Year
category is satisfied by 1995, the MilesperGallon category
is satisfied by 45, the RetailPrice category is satisfied by
7000, and the SalePrice category is satisfied by 6500. The
unique identifier for the second matching record is 0074421.
Each secondary router is configured to send its LST
Response to the user interface agent. The user interface
agent is configured to simultaneously receive each LST
Response from each responding secondary router, to clear out
the free-floating Result Window on the client workstation,
add a header to the Result window, and populate the Result
Window on the client workstation with a display of the

- CA 0220926~ 1997-06-27 --

matching records. Note, in the global mode, the primary
router's LST Response is treated as an LST Response from a
secondary router. For example, in the GUI screen shown in
Fig. 6, the user interface agent has populated the Result
Window with each of the matching records sent from the DBMS
of a secondary server that has been configured to make
available information about motor vehicles offered for sale.
As noted above in connection with the description of
the local search, the user interface agent is configured to
cede to the client user, control over the user interface to
permit the user to scroll through the matching records that
are displayed by the user interface agent in the Result
Window.
In further accordance with the present invention, the
user interface agent is further configured in the global
mode to cede control to the client user to permit the client
user to choose to view more information than is provided in
the matching record. When the client user chooses to view
additional information for a matching record retrieved
during a search conducted in the global mode, the user
interface agent is configured to issue to the secondary
router via the primary router, a request to return the
specific URL of an HTML page that contains additional
information than is contained in the matching record chosen
by the client user. This request is a HOM Request. As
specified in the BNF presented above, the HOM Request
contains a unique listing identifier. An example of a HOM
Request made during a global search is:
http://basx.usconnect.com-RQ,0001,HOM
In this example of a HOM Request, the header is RQ,0001,HOM,
and the unique listing identifier is:
http://basx.usconnect.com.
In accordance with the present invention, the secondary
router is configured so that when the secondary router

54

~- CA 0220926~ 1997-06-27 ~--

receives the HOM Request from the user interface agent via
the primary router, the secondary router parses the HOM
Request and queries the secondary DBMS for detailed
information about the specific row specified in the HOM
Request. The secondary router is configured to retrieve a
pre-existing HTML file if such HTML file exists. However,
if such HTML file does not exist, the secondary router is
configured to build an HTML file from the detailed
information and to save the built HTML file on the secondary
DBMS. The secondary router is configured to format the
information satsifying the HOM Request, into a HOM Response,
which identifies the URL of the matching record that the
client user has chosen to examine on the secondary DBMS. As
specified in the BNF presented above, the HOM Response
contains the Universal Resource Locator of the individual
listing.
An example of a HOM Response from a secondary DBMS that
has been configured to make available information about
motor vehicles offered for sale (the theme of the secondary
DBMS in this example) from the secondary DBMS is:
RS,0001,HOM,URL=HTTP://176.16.9.12:80/auto/chevy/html/5.htm
In this motor vehicle example of a HOM Response, the header
is RS,0001,HOM and is defined by the user interface agent.
The Universal Resource Locator (URL) in this motor vehicle
example is: HTTP://176.16.9.12:80/auto/chevy/html/5.htm.
The secondary router is configured to send the HOM
Response via the primary router to the user interface agent.
The user interface agent is configured to receive the HOM
Response containing the specific URL for the matching record
chosen for ex~;n~tion by the client user. The user
interface agent is further configured to instantiate a
second viewer and to set this second viewer location to the
specific URL for the matching record chosen for examination
by the client user. Fig. 7 depicts the GUI screen that

~- CA 0220926~ 1997-06-27 ,~"
,: . I

displays from a DBMS that has been configured to make
available information about motor vehicles offered for sale
(the theme of the DBMS in this example), the information in
the first one of the matching records depicted in Fig. 6.
In further accordance with the present invention, the
router for each primary/secondary server is configured to
periodically update its profile stored on the Hub DBMS.
This will be done via the COL Request. As schematically
shown in Fig. 2, each router associated with each server
(other than the Hub server) on the network sends
periodically, a COL Request to the Hub router via the
primary router. As specified in the BNF presented above, an
example of a COL Request is:
RQ,O001,COL,HouseType=lStory~tab>3Story¦City=Columbia<tab>Le
xington<tab>Cayce<tab>Red
Bank¦County=T.~;ngton<tab>Richland¦State=SC
In this example of a COL Request, the header is RQ,0001,COL,
and the user interface agent is configured to define the
header portion of the COL Request. In this example of the
COL Request, the DBMS of the initiating server has lStory
and 3Story data in the HouseType category, Columbia,
Lexington, Cayce and Red Bank in the City category,
Lexington and Richland in the County category, and SC in the
State category.
In accordance with the present invention, the Hub
router is configured so that when the Hub router receives
the COL Request from the router of a primary server or a
secondary server, the Hub router parses the COL Request and
checks the COL Request for validity. If the COL Request is
valid, the Hub router is configured to return a COL Response
to the router from which the COL Request originated.
Otherwise, the Hub router will return an ERR Response to the
router from which the COL Request originated. An example of


56

- CA 0220926~ 1997-06-27 ~-

a COL Response, which is formatted as specified in the BNF
described above, is: RS,OOOl,COL,updated
If the COL Request is valid, the Hub router is configured to
use the data in the COL Request to update the profile of the
reporting server in the profile list that is maintained by
the Hub server's DBMS.
This concludes the description of the present invention
when the user interface agent is configured to operate in
the global mode. While a preferred embodiment of the
invention has been described using specific terms in an
embodiment of the invention applied to the purchase and sale
of real estate and the purchase and sale of other products,
such description is for illustrative purposes only, and it
is to be understood that changes and variations may be made
without departing from the spirit or scope of the invention.

,-~~ CA 0220926~ 1997-06-27 ._
.
A ppen~
import tcg.homeconnection.*;
import tcg.tools.*;
import tcg.control.*;
import java.awt.*;
import java.applet.Applet;
import java.net.*;
import java.util.*;

/*******************************************************
* Class: SeekFind
* WriKen by: Brian Duncan
* Date:
* Purpose: This is the main class. This controls
* everything.
*******************************************************/
public class SeekFind extends Applet implements Runnable {
I/Set the Version HERE
public fmal String version = "I.Oe (01/08/97)";
//Have we already ini~i~li7~d?
static boolean initi~li7~d = false;
static boolean firstReshape = true;
Il Main Thread, Animation thread
Thread tMain, tAnimate;
//The Category Panel, shows all available categories
CategoryPanel CatPanel;
//The Query Panel, shows selected search criteria
QueryPanel QPanel;
//The Value Panel, holds all value panels in a card
l/Layout.
Panel VPanel;
CardLayout VLayout;
//Various buttons.
Button SearchButton, HelpButton, ClearAllButton;
Button ClearItemButton, AboutButton;
- //Global/local mode checkbox
Checkbox Globallnd;
//Result Panel - Floating Frame that holds search results
ResultPanel ResultWin;
//Shows current status of applet
StatusBox CurrStatus;
//Splash Screen 5 8

-
CA 02209265 1997-06-27 ,--

StartupCanvas Splash;
//About Box - Floating frame
AboutPanel About;
//Small activiy anirnation
WaitAnimate Animation;
//Headers for CatPanel, Value Panels, and QueryPanel
//These needed to be t~Ytfiel~lc to keep the 3d border.
TextField CatHeader, ValueHeader, QueryHeader;
//Holds the port # of the Primary Router
int primaryPort;
/mle currently selected ValuePanel.
int CurIndex = 0;
//Random # generated to give applet a semi-unique
//ID.
String sessionID;
//Which product type is this applet
U~JpOI li~g?
String ProductType;
//Local or Global.
String initialMode;
String CategoryArgs[l[l = new String[100][5];
//These two will change, based on contents, so they
t/can't be final.
int CATPANELWIDTH = 100;
int VALUEPANELWIDTH = 165;
//Sizes of various components. Did this to
//Allow items to be positioned relative to
//each other.
final int PRIMARY = 0;
final int HUB = l;
final int CATPANELHEIGHT= 120;
final int HEADERHEIGHT = 20;
final int QUERYPANELWIDTH=CATPANELWIDTH+VALUEPANELWIDTH+2;
final int QUERYPANELHEIGHT = 85;
final int BUTTONHEIGHT = 20;
final int BUTTONWIDTH = 60;
final int BUTTONHOFFSET = 5;
final int BUTTONVOFFSET = 2;
Vector of all servers being requested, with the first ([0])
being the Code Base, the second ([I]) being the hub,
and the rest being secondary servers.

CA 0220926~ 1997-06-27 ,-'

Vector Servers;
1/ ServerRequest Servers[];

I*****************************************************************
* Applet initi~li7~tion method
*****************************************************************l
public void initO {
Random r~n~lomi7~r;
int iLoop;
URL tempURL;
String arg;
//Come up with unique idPntifiP- for this session. It will be used
//as applet id in the BNF request/response structure.
r~nrlomi7Pr = new RandomO;
s~cionln = String.valueOf((int)(r~ndorni7~nnextFloatO * 9999));
s~ nm = new String(~oooo~).substring(o~4-s~c~ionTn.lengtho)+spc~ nm;
//Determine which port the applet will be talking to
arg = this.getParameter("PORT");
if(arg != null)
primaryPort = new Integer(arg).intValueO;
else
primaryPort = 7777;
//Determine startup mode for the applet, Local or Global
arg = this.getParameter("MODE");
if(arg != null)
initialMode = arg.toUpperCaseO;
else
initialMode= "LOCAL";
setLayout(null);
//Display Splash Screen
Splash = new StartupCanvas(this);
add("SplashScreen",Splash);
Splash.reshape(O,O,sizeO.width, sizeO.height);
}




I**************************************************
* Start method of Applet's thread
**********************************$******************************1
public void startO {
if (tMain != null && tMain.isAliveO) {
tMain.resumeO;
tAnim~te.resumeO;
} else if(tMain - IIUII){
tMain = new Thread(this);
tMain.setPriority(Thread.MIN_PRIORI~Y);
tMain.startO;
}




} 60

CA 0220926~ 1997-06-27 --


/*****************************************************************
* Stop method of Applet's thread
*****************************************************************/
public void stopO {
if (tMain != null && tMain.isAliveO) {
tM~in cl.cp~dO;
t~nim~t~ cucp~n(lo;
}




I*****************************************************************
* Destroy method of Applet - Overrode this to
* allow for Netscape quirks.
*****************************************************************l
public void destroyO {
if(tMain != null && tMain.isAliveO) {
tMain.resumeO;
tAnim~te resumeO;

}

/*****************************************************************
* Run method of Applet's thread

*~***************************************************************/
public void runO {
Vector categories;
ValuePanel tempPanel;
if(! initi~li7~d) {
//Increment Splash Screen counter
Splash.incCounterO;
//Tniti~1i7e Server Array
Servers = new VectorO;
IlSet Primary Server
Serverc ~dtlT~lernent(new ServerRequest(PRIMARY, this));
((ServerRequest)Servers.elementAt(PRIMARY)) cetT.oç~tion(getCodeBaseO.getHostO, primaryPort,
getCodeBaseO.getFileO);
//create status box
CurrStatus = new StatusBoxO;
//Create Category Panel
CatPanel = new CategoryPanel(lO);
//Create Value Panel
VPanel = new PanelO;
VLayout = new CardLayoutO;
VPanel.setLayout(VLayout); 6 1

- CA 0220926~ 1997-06-27 ~i-

//Request the Category List from the primary server. Make this request modal.
initiateRequest("CAT", PRIMARY);
waitForCompletion(PRIMARY);
//Increment Splash Screen counter
Splash.incCounterO;
}




//Increment Splash screen
Splash.incCounterO;
//Add all value panels to the VPanel.
categories = CatPanel.getAllCategoriesO;
int iCount=0;
for (Enumeration e = categories.el~mentcO; e.hasMoreFlrm~ntc0; iCount++) {
tempPanel = ((ValuePanel) ((Category)e n~ytFl~m~nto).getpanelo);
VPanel.add("ValuePanel"+String.valueOf(iCount), tempPanel);
}




//Create and set up panel headers.
Font f= new Font("Helvetica", Font.BOLD, 12);
CatHeader = new TextField("Features",50);
CatHeader cetFfIit~hle(false);
CatHeader cetR~rl~ground(Color.white);
CatHeader.setFont(f);
ValueHeader= new TextField("Options", 50);
ValueHeader.setEditable(false);
ValueHeader cetR~r~ground(color.white);
ValueHeader.setFont(f);
QueryHeader = new TextField("Selected Features",100);
QueryHeader.cetFtlit~ble(false);
QueryHeader cetR~r~ground(Color.white);
QueryHeader.setFont(f);
//lncrement the splash screen counter.
Splash.incCounterO;
//Create query panel
QPanel = new QueryPanel(this);
ResultWin = new ResultPanel("Seek&Find Search Results", this);
//Create controls
SearchButton = new Button("Search");
HelpButton = new Button("Help");
ClearAllButton = new Button("Clear All");
ClearItemButton = new Button("Clear Item");
AboutButton = new Button("About");
GlobalInd = new Checkbox("Expand Search");
//If initial mode is Global, check the checkbox;
if( initialMode.equals("GLOBAL") ) 62

;~ CA 0220926~ 1997-06-27 ,

Globallnd.setState(true);
//Create Animation thread, panel.
AnimAtion = new WaitAnimate(this);
tAnimate = new Thread(Animation);
t~nim~tf~.ct~tO;
//Increment the splash screen counter.
Splash.incCounterO;
//Request the Hub URL from the Primary Server
initiateRequest("HUB", PRIMARY);
waitForCompletion(PRIMARY);
//Request the Product Type from the Primary Server
Splash.incCounterO;
initiateRequest("TYP", PRIMARY);
waitForCompletion(PRIMARY);
//Increment the splash screen counter
Splash.incCounterO;
//Request the Category values from the Primary Server
if(GlobalTn~ getStateO && GlobalInd.isVisibleO ) {
initiateRequest("VAL", HUB);
waitForCompletion(HUB);
} else {
GlobalTn-l cet~t~te(false);
initiateRequest("VAL", PRIMARY);
waitForCompletion(PRIMARY);
}
//Increment the splash screen counter
Splash.incCounterO;
// Display Data Panels.
add("ValueHeader",ValueHeader);
add("QueryHeader", QueryHeader);
add("CategoryHeader",CatHeader);
add("QueryPanel", QPanel);
add("Status", CurrStatus);
add("CategoryPanel",CatPanel);
add("ValuePanel",VPanel);
// Display controls
add("GlobalInd", GlobalInd);
add("Search", SearchButton);
add("ClearAII", ClearAllButton);
add("ClearItem", ClearItemButton);
add("Help", HelpButton);
add("About", AboutButton);
// Create the Result Panel
add("ResultWin", ResultWin); 63

~- CA 0220926~ 1997-06-27 '-

//Add the ~nim~ n to the applet
add("~nim~tior~ nim~tion);
//Remove the splash screen from the applet.
//Need to keep it, however, to get images.
remove(Splash);
//Set flag so this only happens the first time.
initi~li7~d = true;
//reshape everything
reshape(0,0,thi~ Qi7~0.width, this.sizeO.height);
while(tMain != null)
repaintO;
}




I***************************************************
* Reshape everything, but just the first time.
***************************************************l
public void reshape(int x, int y, int w, int h) {
int iLoop;
int catItemWidth, valueItemWidth, totalWidth, temp;
super.reshape(x, y, w, h);
if (initi~li7Pd && firstReshape) {
//Autosize the Catpanel & Valuepanel based on the
//size of the items in each.
catItemWidth = CatPanel.getMaxCatWidthO+10;
//Allow for scrollbar, if more than 8 categories
if(CatPanel countC~t~goriesO > 8)
catItemWidth+= 1 5;
valueItemWidth = CatPanel.getMaxValueWidthO;
totalWidth = CATPANELWIDTH +
VALUEPANELWIDTH+BUTTONWIDTH+BUTTONHOFFSET+2;
CATPANELWIDTH = totalWidth * (catItemWidth/(catItemWidth+valueItemWidth));
VALUEPANELWIDTH = totalWidth - CATPANELWIDTH;
if(CATPANELWIDTH < catItemWidth) {
CATPANELWIDTH = catItemWidth;
VALUEPANELWIDTH = totalWidth - CATPANELWIDTH;
} else if (VALUEPANELWIDTH < 80) {
VALUEPANELWIDTH = 80;
CATPANELWIDTH = totalWidth - VALUEPANELWIDTH;
}




IlSet the flag so reshape never happens again
firstReshape = false;
//Reshape all components (God, this is ugly!) 64

CA 02209265 1997-06-27 ,~-'

int buttonStart = I +((CATPANELWlDTH+VALUEPANELWIDTH)/2)- -
(((BUTTONWIDTH+2)JS)n);
CatPanel.reshape(l ,BUTTONHEIGHT+2+HEADERHEIGHT+I ,CATPANELWIDTH,CATPANELHEIG
HT);
QPanel.reshape(l ,CATPANELHEIGHT+(HEADERHEIGHT*2)+BUTTONHEIGHT+4,QUERYPANEL
WIDTH,QUERYPANELHEIGHT);
ValueHeader.reshape(CATPANELWIDTH+2, 1 +BUTTONHEIGHT+2,VALUEPANELWIDTH,HEADER
HEIGHT);
QueryHeader.reshape(l ,CATPANELHEIGHT+HEADERHEIGHT+BUTTONHEIGHT+4,QUERYPANE
LWIDTH,HEADERHEIGHT);
Cat~ r reshape( 1,1 +BUTTONHEIGHT+2,CATPANELWIDTH,HEADERHEIGHT);
Glob~lTn-l reshape(b..tton.~Prt, 1,BUTTONWIDTH*2,BUTTONHEIGHT);
SearchButton.reshape(button !~t~rt+((BUTTONWIDTH+2)*2), 1,
BUTTONWIDTH,BUTTONHEIGHT);
HelpButton.reshape(buttonStart+((BUTTONWlDTH+2)*3), 1,
BUTTONWIDTH,BUTTONHEIGHT~;
Abo~ltRutt~ln reshape(button!;;t~rt+((BuTToNwIDTH+2)*4)~ 1,
BUTTONWIDTH,BUTTONHEIGHT);
ClearItemButton reshape(QUERYPANELWIDTH+BUTTONHOFFSET,
((BUTTONHEIGHT+2)*8)+BUTTONVOFFSET, BUTTONWIDTH,BUTTONHEIGHT);
ClearAllButton.reshape(QUERYPANELWIDTH+BUTTONHOFFSET,
((BUTTONHEIGHT+2)*9)+BUTTONVOFFSET, BUTTONWIDTH,BUTTONHEIGHT);
Animation.reshape(QUERYPANELWIDTH+4,CATPANELHElGHT+QUERYPANELHEIGHT+(HEAD
ERHEIGHT*2)+BUTTONHEIGHT+24 - 43, 73, 43);
CurrStatus.reshape(l,
CATPANELHEIGHT+QUERYPANELHEIGHT+(HEADERHEIGHT*2)+BUTTONHEIGHT+4,
QUERYPANELWIDTH, 20);
ResultWin.reshape(50,25,600,330);
//Show the first ValuePanel in the Card Layout.
VLayout.show(VPanel,"ValuePanelO");
VPanel.reshape(CATPANELWIDTH+2,BUTTONHEIGHT+2+HEADERHEIGHT+ 1,
VALUEPANELWIDTH,CATPANELHEIGHT);

CatPanel.listl .select(0);
repaintO;
}
}




I***************************************************
* This switches the value panel when the category
* selected in the CatPanel changes.
***************************************************l
public void update(Graphics g) {
IlHas the CategoryPanel been inct~nti~ted yet? 65

CA 0220926~ 1997-06-27 ,-~

if(CatPanel instanceof CategoryPanel) {
/Met the current index
int tempIndex = CatPanel.listl.getSelect~tlTnd~ YO;
//If the index is different...
if( tempIndex >= 0 && CurIndex != tempIndex) {
//Pull the selections from the current panel
addCriteriaO;
//Change the category selection.
CatPanel.se!ectC~tPgory(tempIndex);
//This is now current.
CurIndex = tempIndex;
//Show the current panel
ValuePanel tempPanel = CatPanel.getCategory(tPmrTndPY).getPanel0;
System out println("ValuePanel"+String.valueOf(CurIndex));
VLayout.show(VPanel,"ValuePanel"+String.valueOf(CurIndex));
Mf this panel needs nrfi~ting do the SUB call.
if(tempPanel.getNeedsRefreshO)
getSubValues(tempPanel.getNarneO);
}
}




I**************************************************
* Did this to try and get rid of double-clicking
**************************************************l
public boolean mouseDown(Event evt, int x, int y) {
if(evt.clickCount < 2 && (evt.target in~t~nceof BuKon 11 evt.target instanceof Checkbox))
return false;
else
return true;
}




I**************************************************
* Action event. Find out what happened, and act on it.
**************************************************l
public boolean action(Event evt, Object arg) {
boolean returnValue = false;
Il Search buKon pushed. Check checkbox state, if true, perform
Il global search, otherwise perform local search.
if(arg.equals("Search")) {
addCriteriaO;
returnValue = true;
if( QPanel.conntTt~ m~O > 0) {
ResultWin.clearA110; 6 6

- CA 0220926~ 1997-06-27

if(Globallnd.getStateO) {
initiateRequest("PRO", HUB);
} else {
getT ictingc(pRIMARY);
ResultWin .showO;
} else ~
showError("Can't Search","To search, you must select\nat least one feature.");
} else if(arg.equals("Help")) {
t/ Help button pressed. Attempt to inct~nri~te new Browser,
Il Set URL to the Help URL page.
retumValue = true;
URL ThisURL;
tr,Y {
ThisURL = new URL(getCodeBase0,"/help/hçlphr htm");
getAppletContextO.showDocurnent(ThisURL, "Help");
} catch(Exception e) {
SystPm ollt println("oops! Couldn't connect to Help HTML!");
}




else if(evt.target in~t~nreof Checkbox) {
The checkbox was clicked. repopulate
values
retumValue = true;
/IWe need to clear out all existing values first.
CatPanel.deselectA110;
/IDo VAL request either Globally, or locally
if( GlobalInd.getState0)
initiateRequest("VAL",HUB);
else
initiateRequest("VAL",PRIMARY);
//Kill the query panel entries.
QPanel.clearA110;
else if(arg.equals("About")) {
//About button pressed. Let's see if we can't
/Imake it modal...
retumValue = true;
if(About=null) {
About = new AboutPanel("About Seek~Find", this);
add("AboutBox",About);
About.reshape(50,25,3 00,3 00);
About.showO;
else if(arg.equals("Clear Item")) { 6 7

-- CA 0220926~ 1997-06-27 ¢-

//Clear Item Button - Clears selected Query Item
returnValue = true;
CatPanel.getCategory(CurIndex).deselectAI10;
QPanel.clearCurrentO;
else if(arg.equals("Clear All")) {
//Clear All Button - Clears Query Panel
returnValue = true;
QPanel.clearA110;
CatPanel desel~ctA110;

.
return returnValue;
}




/**************************************************
* Handle custom everlts
**************************************************l
public boolean handleEvent(Event evt) {
//Custom Event. Did this to directly link a select
t/with the applet.
if( evt.id = 10001) {
//Add criteria from current value panel to
//Query Panel
addCriteriaO;
//Check to see if this category has any dependents.
checkForSubs(((ValuePanel)evt.target).getNameO);

}
return super.handleEvent(evt);
}




/**************************************************
* Clears out all categories that are prerequisite
* to this one (argS).
**************************************************/
public void checkForSubs(String argS) {
String pl ~l c;~uisiL~,
String catName = argS;
Category whichOne;
Vector Values;
/IGet a vector of all categories that are children
Vector categories = CatPanel.getPrerequisites(catName);
//Loop through them all, clearing the selections out,
//and killing the query selections.
for( int iLoop = 0; iLoop < categories.sizeO; iLoop~ ) {
whichOoe = (Category) categories.elementAt(iLoo~);
whichOne.clearA110; - 6

CA 0220926~ 1997-06-27 Ir~

QPanel.clearItem(whichOne.getNarneO);
//Need to do this recursively, because this child
//may also have children.
checkForSubs(whichOne getNameO);
//If the prerequisite category has a user's selection,
//the children need to be set to repopulate when
//selected
if(!((String)CatPanel.getCategory(catName).getValuesO.elementAt(O)).equals("None"))
whichOne.setNeedsRefresh(true);
}




}
/**************************************************
* Add the criteria entered or selected in the current
* value panel to the query panel.
**************************************************/
public void addCriteriaO {
//Only let this happen if everything has been initi~li7Pd
if(initi~li7Pd) {
Vector Values;
String Name, Header;
Category CurCategory;
//Get the cus-rent category.
CurCategory = CatPanel.getCategory(CurIndex);
Nasne = CurCategory.getNameO;
Header= CurCategory.getHeaderO;
Values = CurCategory.getValuesO;
//Add the selections to the Query panel.
QParsel.addQuery(Name, Header, Values);
}
}




/**************************************************
* Set the status box with the ap~SuS"idt~ message, start or
* stop tlle ~nim~tion ~s,,oysiat~ly~
**************************************************/
public void setStatus(String sArg) {
if (tArssmate != null) {
if (sArg.equals("Ready")) {
//Activity's done, give the users their
//buttons back
enableButtonsO;
//Turn the anisnation off
Anim~tion cetMotion(false);
//Set the cursor back to a nos-mal cursor.
if (!(ResultWin = null)) {
ResultWin.setCursor(Frame.DEFAULT_CURSOR);

CA 0220926~ 1997-06-27 -

3 else {
//Activity's goin' on, take the buttons away.
disableButtonsO;
// ~nim~tion cetMotion(true);
//Set the cursor to a 'HOLD IT!' cursor
if (!(ResultWin = null)) {
ResultWin.setCursor(Frame.WAIT_CURSOR);

}
}
CurrSt~hlc cet~tatus(sArg);
}




/********$*************
* Turns all the buttons off
**************************************************/
public void disablf Ruttonc0 {
SearchB--tt-n ~lic~bleo;
HelpBntton ~lic~hleo;
Clear~llRutton tlic~hleO;
ClearTtPmR--tton 11ic~bleo;
Abo--tRulton ~lic~hleo;
Glob~lTnrl disableO;
}




/************************************************** :
* Turns all the buttons on
**************************************************/
public void enableBuKons0 {
- SearchButton.enableO;
HelpButton ~n~h~leo;
ClearAllButton-enableO;
ClearItemButton-enableO;
AboutBntton en~hleo;
Glob~lTnfl en~hleO;
}
/**************************************************
* Pop up an error message.
**************************************************/
public void showError(String title, String message) {
ErrorDialog errorDialog;
if(message l~ctTn~l~YOf(~]~) > o)
message = message.substring(message l~ctTn-le~cOf("]")+1)+
"\nPlease contact the Webm lct~r ~;
errorDlalog = new ErrorDialog(title, message);
add("ErrorDialog", errorDialog);
errorDialog.setResizable(false);
errorDialog.reshape(200,200,300, 1 50);
errorDialog-showO;
} 70

-- CA 0220926~ 1997-06-27


/**************************************************
* Parses the CAT response, and sets the CatPanel
* categories.
**************************************************l
void parseCategoryResponse(Shring ArgS) {
String name, header, length, type, prerequisite;
Vector vFlPmPntc, vCategories;
I/Is the response valid?
if (ArgS.lengthO > ~ ) {
//Split the response into Category-sized chunks
vCategories = M~nirul~tion crlit(~ ArgS);
//Loop through the category chunks
- for( Enumeration e = vC~tcgo-ics.elementsO;e.hasMoreElementsO;) {
//Split each category chunk into category info
//chunks
vF.lementc = Manipulation.split(~,(Sh-ing)e ne~tFlPmentO);
name = (String)vElements.elementAt(O);
header = (Sh ing)vFlementi elementAt(l);
length = (String)vFI~m~ntc el~mentAt(2);
type = (String)vElem~nt~ ~lPm~nt~t(3);
//If there's no prerequisite, set it to "".
if(vElement~ Ci7~'0 > 4) {
prerequisite = (Shing)vElements.elementAt(4);
} else {
prerequisite= "";
}
//Add a new category to the Category panel.
CatPanel.addCategory(name, header, length, type, prerequisite);
}
}




/**************************************************
* Makes the CAT request to the primary server
***********************$**************************/
public void getCategoriesO {
Shring outString, response;
setSt~hlc("Requesting Categories...");
//Build the request string.
outSh:ing = makeRouterSh ing("", "cat", false);
//Make the request
response = ((ServerRequest)Servers.elementAt(PRIMARY)).getRouterResponse(outString);
//Get the response
parseCategoryResponse(response); 7 1

- CA 0220926~ 1997-06-27 r'~


setStatus("Ready");

I**************************************************
* Makes the HUB request to the Primary Server
**************************************************/
public void getHubO {
Strillg outString;
String response;
setStatus("Requesting the Hub URL...");
//Build the request string
outString = makeRouterString("", "hub", false);
//Make the request
response = ((ServerRequest)Servers.elementAt(PRIMARY)).getRouterResponse(outString);
//Parse the response
parseHubResponse(response);
setStatus("Ready");
}




I**************************************************
* Makes the TYP request to the primary server
**************************************************l
public void getProductTypeO {
String outString;
String response;
setStatus("Requesting the Product Type...");
//Build the request string.
outString = makeRouterString("", "typ", false);
//Make the request
response = ((ServerRequest)Servers.elementAt(PRIMARY)).getRouterResponse(outString);
//Parse the response
parseTypResponse(response);
setStatus("Ready");
}




I**************************************************
* Makes the SUB request for a specific Category
**************************************************l
public void getSubValues(String argS) {

IlGet the category that matches this name
Category category = CatPanel.getCategory(argS); 7 2

CA 0220926~ 1997-06-27 ,~


//lf Local, request to the Primary Router,
//Otherwise request to the Hub
if(GlobalInd.getStateO && Globallnd.isVisibleO ) {
initiateRequest("SUB", HUB, category);
waitForCompletion(HUB);
} else {
GlobalInd.setState(false);
initiateRequest("SUB", PRIMARY, category);
waitForCompletion(PRIMARY);
}
//This category no longer needs refreshing
category.setNeedsRefresh(false);
}




I**************************************************
* Makes the VAL request
**************************************************l
public void populateValues(int ServerNum) {
Sh ing CatString = "";
String outSh ing = "";
String response = "";
String p,~ Ui:~itt;
String Type;
Category whichOne;
Vector categories;
setSPhlc("Requesting Category Selections ");
categories = CatPanel.getAllCategoriesO;
//Loop through all the categories, pulling out the
//ones that are Dyn~mi~T ict or StaticList
for(Enumeration e = categories.el~mPntc0; e.hasMoreElementsO; ) {
whichOne = (Category) e.nextElementO;
Type = whichOne.getTypeO;
if(Type equ~le("Dyn~micT ict") 1I Type.equals("StaticList"))
/ADetermine if this category has a ~ equiaite
//If it does, skip it.
if(whichOne.getPrerequisiteO.lengthO = O)
CatShring = CatString + whichOne.getNameO + "I";
}




//Strip the last "I" off
CatShing = CatStr ng cubstring(o~ CatString l~ngthO-I);
//If global, request from Hub, otherwise, request
//from Primary router.
if (ServerNum = HUB) {
outString = makeRouterShing(ProductType+","+CatString, "val", h-ue);
} else {
outString = makeRouterShring(CatString, "val", false);
} 73

-- CA 0220926~ 1997-06-27 ,~
;: .

//Make request.
response = ((ServerRequest)Servers.elementAt(ServerNum)).getRouterResponse(outString);
//Parse response
parseValueResponse(response);
set~t~ c("Ready");
}




I**************************************************
* Parse Sub response, and populate appl olJI idt~
* category
**************************************************l
public void populateSubValues(int ServerNum, Object category) {
String CatString = "";
String outString;
String response = "";
Vector values;
set~t~hlc("Requesting Selectionc- "+((Category)category).getHeaderO);
CatString = ((Category)category).getNameO+"=";
IlGet the values from prerequisite category
values = CatPanel.getCategory(((Category)category).getPrerequisiteO).getValues0;
CatString = CatString + Manipulationjoin("~t",values);
IlIf global, request to hub, otherwise, request to
//Prirnary router
if (ServerNum = HIJB) {
outString = makeRouterString(ProductType+","+CatString, "sub", true);
} else {
outString = makeRouterString(CatString, "sub", false);
}




//Make request
response = ((ServerRequest)Servers.elementAt(ServerNum)).getRouterResponse(outString);
//Parse response
parseValueResponse(response);
setst~tllc("Ready");
}




/**************************************************
* Adds a request header to the request string.
**************************************************l
public String makeRouterString(String reqData, String reqType, boolean isHub) {
String outString;
if (isHub) {
outString = "RH,";
} else {

- CA 0220926~ 1997-06-27 ;-

outString= "RQ,";
}
outString += sessionlD+","+reqType+","+reqData;
return outString;

/**************************************************
* Parses the hub response, and creates hub object
**************************************************l
public void parseHubResponse(String ArgS) {
Il If response contains a URL, create the hub Server object,
Il Otherwise hide Global checkbox, which will limit user
Il to local searches.
if(ArgS != null && !ArgS.toLowerCaseO.equals("none")) {
Serv~s ~ Flprn~nt(new ServerRequest(HUB, this));
((ServerRequest) Servers elem~nt~t(HUB)) cet~.o~tion(ArgS);
} else {
Glob~lTn~l hide0;
}
I**************************************************
* Parses the Product Type response.
**************************************************l
public void parseTypResponse(String ArgS) {
ProductType = ArgS;
} ::
I**************************************************
* Parses the VAL response, populating ap~ ylia~e
* Categories
**************************************************l
public void parseValueResponse(String ArgS) {
Vector vCategories, vValues;
int BodyPos, EqualPos, iLoop;
String Narne, nextSection;
Category CurCategory;
//Break response into category-sized chunks
vCategories = Manipulation.split('l',ArgS);
I/Loop through the category chunks
for(Enumeration e = vCategories.elementsO;e.hasMoreElements0;) {
nextSection = (String) e.nextElementO;
EqualPos - riextSection indexOf("=");
Name = nextSection.substring(0,EqualPos);
/IBreak category into value-sized chunks
vValues = Manipulation.split(~, nextSectinn cnh.~t~ing(EqualPos+1));
CurCategory = CatPanel.getCategory(Name);

~ CA 0220926~ 1997-06-27 ~-
i~

CurCategory.clearAI10;
//Add the values to the category list.
CurCategory ~TtPmc(vvalues);
}




}
I**************************************************
* Parses the LST response, and populates the
* result window
**************************************************l
public void pars~T ictingResponse(String ArgS, int ArgI) {
Vector vListing, vValues;
String n,oYtT.ictine;
if (ArgS.lengthO > ~) {
//Break ~ ullse into listing-sized chunks
vListing = Manipul~tion cplit("ll",ArgS);
vValues = new VectorO;
/tBreak listing chunk into column-sized chunks
for( Enumeration eListing = vl.ictinp elementsO; ~T.icting h~cMoreT~.lemPntcO; ) {
nPYtT ictine = (String) eT.icting neYtT-lPmentO;
vV~ s ~ Flpment(Manipulation.split(ll~>n~ytT ictinp));
//Add a listing to the result window.
ResultWin ~ Ttemc(vValues, ArgI);
} else {
showError("No results retumed", "Your search did not retum any results.\nTry selecting different
features,\nor eYp~n-ling search.");

}
I************************************************** :'
* Parses the PRO response
**************************************************l
public Vector parseProfileResponse(String ArgS) {
Vector vServers;
//Split response into server-sized chunks
vServers = Manipulation.split('l',ArgS);
return vServers;
}




I**************************************************
* Parses the ADV response, adding the ads to the
* Resultwindow for use on the tickertape.
**************************************************l
public void parseAdResponse(String ArgS) {
Vector vSections, vURLs, vMessages, vTemp;
vSections = Manipulation.split('l',ArgS); 7 6

-- CA 0220926~ 1997-06-27 ~'-

vURLs = new VectorO;
vMessages = new VectorO;
//Split all the messages and URL's out
for(Enumeration e = vSections.elementc(); e.hasMoreElementsO;) {
vTemp = Manipul ition cplit(~t', (String)e n~YtFl~ment0);
vMessages.addElement((String)vTemp.elementAt(0));
vURT.c adrlFlement((string)vTemp elementAt(l));
}
//Pass the ads to the result window
ResultWin.addAds(vMessages, vURLs);
}
I**************************************************
* Parses the HOM response, passing URL to the browser
**************************************************l
public void parseHomeResponse(String ArgS, int ArgI) {
URL ListingURL;
try {
ListingURL = new URL(ArgS);
this.getAppletContextO.showDocument(ListingURL, "Home Listing");
} catch (MalformedURLException e) {
System.out.println("Didn't connect to web page "+ArgS+"\n");
}




/
* Request profile from HUB, create server objects from response
* request listings from all servers retumed.
**************************************************l
public void getGlob~lT.i~tingc0 {
String response;
Vector ServerURL;
ServerThread tThread;
int iLoop;
//Get ads from Hub
response = QueryForAds(HUB);
//Parse ad response
parseAdResponse(response);
//Get servers to query from Hub
response = QueryForProfile(HUB);
ServerURL = parseProfileResponse(response);
//Do this to kill any old Secondary Servers. 7 7
Servers .setSize(2);

-~ CA 0220926~ 1997-06-27 ,.-


//Create server objects for all servers, and do LST
//request for each of them
for( iLoop = 0; iLoop < ServerURL.sizeO; iLoop++) {
Servers.addElement(new ServerRequest( iLoop+2, this));
((ServerRequest)Servers.elementAt(iLoop+2)).setLocation((String)ServerURL.elementAt(iLoop));
get~ .ictinpc(iLoop+2);
}
}




/**************************************************
* Kick off LST request
**************************************************l
public void getT ictingC(int ArgI) {
initiateRequest("LST",ArgI);
}




I**************************************************
* Request listings from secondary server
**************************************************/
public void QueryForListings(int ServerNum) {
String Request;
String outString = "";
String response= "";
setStatus("Requesting T .ictingc
- //Get request from Query panel
Request= QPanel.getRequest(true);
I/Build request string
outString = makeRouterString(Request, "lst", false);
//Make request
response = ((ServerRequest) Servers.elementAt(ServerNum)).getRouterResponse(outString);
I/Parse response
parseListingResponse(response, ServerNum);
setStatus("Ready");
}




,, I * ***** ***************************************
* Make HOM request
**************************************************/
public void QueryForHome(int ServerNum) {
String Request;
String outString= "";
String response = ""; 7 8

-- CA 0220926~ 1997-06-27 --

setStatus("Requesting a Listing Page...");
/IGet the unique identifier for currently
//selected listing.
Request = ResultWin.getCurrentNumberO;
//Build request string
outString = makeRouterString(Request, "hom", false);
//Make request
response = ((ServerRequest) Servers.elementAt(ServerNum)).getRouterResponse(outString);
//Parse response
parseHomeResponse(response, ServerNum);
set~t~h-c("Ready");
}




I**************************************************
* Make PRO request
***********************$**************************/
public String QueryForProfile(int ServerNum) {
String Request;
Strulg outString = "";
String response = "";
set~t~t-lc("Querying for Servers...");
/IGet query from Query Panel
Request = QPanel.getRequest(false);
//Build request string
outString = makeRouterString(ProductType+","+Request, "pro", true);
//Make request
response = ((ServerRequest) Servers.elementAt(ServerNum)).getRouterResponse(outString);

set~t~c("Ready");
return response;
}




/**********************************$***************
* Make ADV Request
**************************************************l
public String QueryForAds(int ServerNum) {
String Request;
String outString = "";
String response = "";
setStatus("Querying for Ads.. "); 7 9

CA 0220926~ 1997-06-27

IlGet query from Query Panel
Request = QPanel.getRequest(false);
//build request string
outString = makeRouterString(ProductType+","+Request, "adv", true);
//Make request
response = ((ServerRequest) Servers.elementAt(ServerNum)).getRouterResponse(outString);
setStatus("Ready");
return response;
}
/*********************************************************
* ClearingHouse function for all requests, parameters are
* Request Type and ServerNumber.
*********************************************************l
public void initiateRequest(String ArgS, int ArgI, Object argO) {
ServerRequest tempServer = (ServerRequest) Serv~rs ~l~rn~nt~t(ArgI);
//Set inforrn~tion for server to make request.
tempServer.setType(ArgS);
tempServer.setArg(argO);
//Kick the request thread off.
tempServer.startThreadO;
}




/**************************************************
* Convenience method version of initiateRequest, w/o argument.
**************************************************/
public void initiateRequest(String ArgS, int ArgI) {
initiateRequest(ArgS, ArgI, "");
}




/**************************************************
* This method makes the Server Thread modal
**************************************************/
public void waitForCompletion(int ArgI) {
while(!((ServerRequest) Servers.elementAt(ArgI)).getCompleteO) {
repaintO;
tMain.yieldO;

}

/**************************************************
* Get Seek&find's version
****~*********************************************/
public String getVersionO {
return version;
} 80

CA 0220926~ 1997-06-27

import java.awt.*;
import java.net.*;

I*****************************************************
* Class: WaitAnimate
* Written by: Brian Duncan
* Date:
* Purpose: This class ~nc~rs~ tes functionality of anirnation that moves
* when the applet is is a wait state.
*******************************************************l
public class WaitAnimate extends Panel implements Runnable {
protected int whichPic = -1;
boolean Animate = false;
boolean first = true;
int direction = l;
SeekFind cParent;
boolean finalDrawn = false;
public WaitAnimate(SeekFind ArgC) {
cParent = ArgC;
}




public void setMotion(boolean bArg) {
Animate = bArg;
}




public void runO {
int iLoop;
Il first=true;
// paint(this.getGraphicsO);
while (true) {
try {
Thread.sleep(1 50);
} catch (Interrupte~iFY~eption e) f};
if (Animate) {
whichPic~;
if( whichPic > 16 ) {
whichPic = O;
}




repaintO;
} else {
if(whichPic != 99) {
finalDrawn=false;
whichPic = 99;
repaintO;

} } 8 1

CA 02209265 1997-06-27


}
public void paint(Graphics g) {
g.setColor(Color.gray);
drawTopLeftLines(g, 0,0,73,43);
g.setColor(Color.gray);
drawBottomRightLines(g,0,0,73 ,43);
if(whichPic=99) {
finalD,aw~ ue;
for(int iLoop=0;iLoop < 17; iLoop++) {
cPar~nt ~pl~ch drawOverlay(iLoop, thic g~tl~raphics0, 3, 3, 67, 37);
}




} else {
cParent.Splash.drawOverlay(whichPic, this.getGraphicsO, 3, 3, 67, 37);
}
}




//Override update with this to stop flickering.
public void update(Graphics g) {
paint(g);
}
public void drawTopLeftLines(Graphics g, int x, int y, int width, int height) {
g.setColor(g.getColorO.brighterO.brighterO);
for(int i=0; i<3; i++) {
g.drâwLine(x+i~ y+i, x+width-(i+l), y+i);
g.drawLine(x+i, y+i+l, x+i, y+height-(i+l));

}
public void drawBottomRightT in~s(Graphics g, int x, int y, int width, int height) {
for(int i=l; i<=3; i++) {
g.drawLine(x+i-l, y+height-i, x+width-i, y+height-i);
g.drawLine(x+width-i, y+i-l, x+width-i, y+height-i);
}
}




82

CA 0220926~ 1997-06-27

import java.awt.*;
import java.util.*;
import java.io.*;
import java.net.*;
import tcg.tools.*;

/*************************************~*****************
* Class: StartupCanvas
* Written by: Brian Duncan
* Date:
* Purpose: This class provides splash screen fimctionality, as well as
* Image ~nim~
*******************************************************l
public class StartupCanvas extends Panel {
Vector destCoord, sourceCoord, sizeCoord, imageNames;
Image collage, startup;
SeekFind cParent;
int imageCounter= 0;
int left, top;
boolean first = true;
int mainHeight, mainWidth;
int lastDrawn--I;
public StartupCanvas(SeekFind ArgC) {
cParent = ArgC;
getImagesO;
}




- publicvoidpaint(Graphics g) {
int fLeft, frop;
if (first) {
first=false;
Font f= new Font("TimesRoman", Font.PLAIN, 26);
FontMetrics fm = getFontMetrics(f);
String fMessage = "Please wait, loading...";
left = (int)((cParent.sizeO.width-mainWidth)/2);
top = (int)((cParent.sizeO.height-mainHeight)/2);
fLeft = (cParent.sizeO.width - fm.stringWidth(fMessage)) /2;
fTop = (top + 180);
g.setFont(f);
g.drawString(fMessage, fLeft, fTop);
g.draw3DRect(le~- I ,top- I ,mainWidth+2,mainHeight+2,true);
drawBaseImage(this.getGraphicsO, left, top, mainWidth-1, mainHeight-l);
} 83

CA 0220926~ 1997-06-27
'~

1/ Override update with this to stop flickering.
public void update(Graphics g) {
// drawOverlay(imageCounter, g, left, top, mainWidth-l, mainHeight-l);
}




public void drawLogo(Graphics g, int lef~, int top, int width, int height) {
drawLogo(imageN~mec Ci71'0-1, g, left, top, width, height);
}
public void drawLogo(int whichImage, Graphics g, int le~, int top, int width, int height) {
this.draw~PTm~ee(g, left, top, width, height);
for( int Loop = 0; iLoop <= whichImage; iLoop~) {
this.drawOverlay(iLoop, g, left, top, width, height);
}




/I g.setPaintModeO;
// paint(g);
}
public void drawBaseImage(Graphics g, int left, int top, int width, int height) {
g.drawImage(startup, left, top, width, height, this);
};
public boolean incCounterO {
imageCounter++;
repaintO;
if(imageCounter > imageNames.sizeO-l)
imageCounter= imageNames.sizeO-l;

drawOverlay(imageCounter, this.getGraphicsO, left, top, mainWidth-1, mainHeight-l);
imageCountert~;
repaintO;
if(imageCounter > imageNames sizeO-I)
imageCounter= imageNames.size0-1;

drawOverlay(imageCounter, this.getGraphicsO, left, top, mainWidth-l, mainHeight-l);
return true;
}




public void drawOverlay(int whichImage, Graphics g, int argIl, int argI2, int argI3, int argI4) {
// public synchronized void drawOverlay(int whichImage, Graphics g, int argIl, int argI2, int argI3, int
argI4) {
float widthPct = (float) argI3/(mainWidth-l);
float heightPct = (float) argI4/(mainHeight- I );
int x = argIl;
int y = argI2;
int iWidth, iHeight;
int iX, iY, iSX, iSY; 84

CA 0220926~ 1997-06-27

String imageName;
F~ect~ngle oldClip = g.getClipRectO;
repaintO;
if(lastDrawn<=O ¦¦ whichrm~Pe =O)
this.drawR~cerm~ge(g, argII, argl2, argI3, argI4);
if(imageNames.sizeO < 16)
whichImage=(int)(whichImage*((float)imageNames.sizeO/I 6));
// if(lastDrawn = imageNames ci~O l)
// lastDrawn=0;
for(int iLoop=M~th m~y(lastDrawn~o);iLoop <=whichTm~ge;iLoop++) {
iWidth=((Point)ci7PCoorrl el~ment~t(iLoop)).x;
iHeight=((Point)sizeCoord.elementAt(iLoop)).y;
iX=((Point)dfftCoor~l el~ment~t(iLoop)).x;
iY=((Point)destCoord.elementAt(iLoop)).y;
iSX=iX-((Point)sourceCoord.elementAt(iLoop)).x+x;
iSY=iY-((Point)sourceCoord.elementAt(iLoop)).y+y;
g.clipRect((int)((float)iX*widthPct)+x, (int)((float)iY*heightPct)+y+1, (int)((float)iWidth~widWct),
(int)((float)iHeight*heightPct));
// g.drawImage(collage,(int)((float)iSX*widWct), (int)((float)(iSY*heightPct)+2),
(int)((float)collage.getWidth(this)*widthPct), (int)((float)collage.getHeight(this)*heightPct), cParent);
g.drawImage(collage,(int)((float)iSX*widthPct), (int)((float)(iSY*heightPct)+2),(int)((float)collage.getWidth(this)*widthPct), (int)((float)collage.getHeight(this)*heightPct), cParent);
}




g.clipRect(oldClip.x, oldClip.y, oldClip.width, oldClip.height);
lastDrawn = whichTm~ge;
}
public void getImagesO {
DataInputStream dIn;
String tempName, line;
Vector temp;
Point tempCoord;
MediaTracker tracker;
line= "First";
try {
dIn = new DataInputStream((new URL(cParent.getCodeBaseO,"startup.map").openStreamO));
imageNames = new VectorO;
destCoord = new VectorO;
sourceCoord = new VectorO;
sizeCoord = new VectorO;
line = dIn.readLineO;
temp = Manip~ tit~n cplit(',', line);
tempName = (Strirlg)temp.elementAt(0);
mainWidth=(new Integer((String)temp.elementAt(l)).intValueO);
mainHeight=(new Integer((String)temp.elementA8t~2)).intValueO);

_ CA 0220926~ 1997-06-27

whiletline != null && line.trimO.length()>O) {
line = dIn.readLineO;
if(line != null && line.trimO.lengthO>O) {
temp = Manipulation.split(',', line);
imageNames.addElement(temp.elementAt(O));
tempCoord = new Point(new Integer((String)temp.elementAt(l)).intValueO,new
Integer((String)temp.elementAt(2)). intValueO);
destCoord.addElement(tempCoord);
tempCoord = new Point(new Integer((String)temp.elementAt(3)).intValueO,new
Integer((String)temp.elementAt(4)).intValueO);
sizeCoor~ Flpment(tempcoord);
tempCoord = new Point(new Integer((String)temp.elementAt(5)).intValueO,new
Integer((String)temp.elementAt(6)).intValueO);
sourceCoord.addElement(tempCoord);
}




collage = cParent.getImage(cParent.getCodeBaseO, "images/collage.gif ');
startup = cParent.getImage(cParent.getCodeBaseO, "images/startup.gif ');
tracker = new MediaTracker(cParent);
tracker ~ m~ge(collage,O);
tracker ~ Tm~pe(startup~
for(int Loop=O;Loop<2;iLoop++) {
cParent.showStatus("Loading Startup Image: "+String.valueOf(iLoop+l));
try {
tracker.waitForID(iLoop);
} catch(InterruptedException e) {};
catch(lOException e) {
SystPm ol.t println("lJnable to open Image map file!");
}




}




86

CA 0220926~ 1997-06-27

import tcg.homeconnection.*;
import java.io.*;
import java.net.*;

I**********************************************
* Class: SeverThread
* Written by: Brian Duncan
* Date:
* Purpose: This class is an ~Ytencion of Thread.
* The purpose of this is to allow a Server class
* to receive a response from a server, without
* tying the system up. This allows seek&fuld to
* process multiple requests simultaneously.
**********************************************/
class ServerThread extends Thread {
SeekFind cParent;
int ServerNumber;

I**********************************************
* Constructor
**********************************************l
public ServerThread(SeekFind Main, int iArg)
cParent = Main;
ServerNumber= iArg;
}




I**********************************************
* The runO method of this thread. Will process
- * different request-builder methods of the SeekFind class
* based on the type of request.
**********************************************l
public void runO {
boolean Successful = false;
InputStream fResponse;
ServerRequest tempServer;
String requestType;
tempServer= (ServerRequest) cParent.Servers.elementAt(ServerNumber);
requestType = tempServer.RequestType;
1/ Call app.o~liale request function based on Type
if(requestType.equals("CAT"))
cParent.getCategoriesO;
else if(requestType.equals("HUB"))
cParent.getHubO;
else if(requestType.equals("TYP"))
cParent.getProductTypeO;
- else if(requestType.equals("VAL"))
cParent.populateValues(ServerNumber);
else if(requestType.equals("SUB"))
cParent.populateSubValues(ServerNumber, tem~Server.arg);
else if(requestType.equals("PRO")) 7

CA 02209265 1997-06-27
.:
cParent.getGlob~l~ .ictinecO;
else if(requestType.equals("HOM"))
cParent.QueryForHome(ServerNumber);
else if(requestType.equals("LST"))
cParent.QueryForListings(ServerNumber);
IlSet the server object completion status to true.
tempServer.setComplete(true);
}
}




88

~ CA 0220926~ 1997-06-27 _
,

import tcg.homeconnection.*;
impor~ java.io.*;
import java.net.*;

1****~*******************~**************************
* Class: ServerRequest
* Written by: Brian Duncan
* Date:
* Purpose: This class .onc~rsul~t~s all the connection
* and state inforrnation about a router (Server-side
* ja~a application).
********$******************************************/
class ServerRequest {
SeekFind cParent;
//Unique serYer number - used system-wide
int S~rverNumber;
//D~chn~tion URL
Strinv destin~tion;
//Host IP Address
Strinv Host;
//Server Port #
int Port;
//Server file. Used to keep track of sub-directory info
String File;
//The current request type in process.
String RequestType;
//Argument to be used when processing the request.
Object arg;
InputStream InStrearn;
OutputStream OutStream;
//Determines the state of the request to this server
boolean Complete = false;
Socket Sock;

/*****~****************************************
* Constructor
*****~************************Y***************/
public ServerRequest(int iArg, SeekFind aArg) {
ServerNumber= iArg;
cParent = aArg;

/*****~***************************************
* Sets the completion status of the current 8 9

CA 0220926~ 1997-06-27
;

* request for this server.
*****$****************************************/
public void setComplete(boolean bArg) {
Complete = bArg;
}
I**********************************************
* Gets the completion status of the culrent
* request for this server
********************$*************************/
public boolean getCompleteO {
return Complete;




/**********************************************
* Sets the request type for the current request
* to the server.
**********************************************l
public void setType(String ArgS) {
RequestType = ArgS;
setCnmplete(false);
}




/**********************************************
* Sets the argument (If any) to be used when
* processing the current request or response.
***********************J******************/
public void setArg(Object ArgO) {
arg = ArgO;
}




/*$********************************************
* Sets the location url info for this server
* This version takes a complete URL String as a parameter.
**********************************************l

public void setT oc~on(String ArgS) {
Stin~tion = ArgS;
try {
URL tempURL = new URL(ArgS);
Host = templlRL.getHost0;
Port = tempURL.getPort0;
if( Port = - I )
Port = cParent pri~naryPort;
} catch (M~lformedURLException e) {
System.out.println("Well, couldn't set the location!\n");


/**********************************************
* Sets the location url info for this server
* This version takes Host (String), Port (Int)~ and
* File/pa~ (String) as parameters.
*************** * J


CA 0220926~ 1997-06-27

public void setLocation(String ArgS, int ArgI, String Ar~S2) {
Host = ArgS;
Port = ArgI;
File = ArgS2;
if( Port = - I )
Port= 80;
destination = "http://"+Host+": "~String.valueOf(Port)+File;
}
I**********************************************
* Returns the Host name/IP address of this server
**********************************************/
public String getHostO {
return Host;
}
/**********************************************
* Retums the Port # of this server
**********************************************l
public int getPortO {
return Port;
} ~ :

* * *
* Returns the Input Stream of this server
**********************************************/
public InputStream getInStreamO {
return InStream;
} :
/**********************************************
* Returns the Output stream of this server
***********************$**********************/
public OutputStream getOutString0 {
return OutStream;
}




/**********************************************
* Opens a connection to the server, and processes
* a request. Parameter is the request string.
**********************************************/
public String getRouterResponse(String ArgS) {
String response = "";
boolean Body = false;
DataInputStream DStream;
ServerRequest tempServer;
try {
tempServer= (ServerRequest) cParent.Servers.elementAt(0);
Sock = new Socket(tempServer.getHostO,tempServer.getPort0);
DStream = new DataInputStream(Sock.getInputStreamO);
sendRouterRequest(ArgS); 9 1

CA 0220926~ 1997-06-27 .
, .

response = DStream.readLineO;
//Check for error
if(responce,cl~kstring(8,1 I).toLowerCaseO.equals("err")) {
cParent.showError("Router Error: "+response.substring(12, 15), resp-~rl~ç ~uhstring(17));
response = "";




Sock.closeO;
catch (Exception e) {
cParent.showError("Router Not Responding", "Please try again later.");
response = "";
System.out.println(e+" (Error receiving Router Response)");
}




//Truncate the header of the response.
if( r~s~l-nc~ lengthO > 11 )
response = r~poncç ~ubst~ing(12);
else
response = "";
return ~ onse;
}




1****~*****************************************
* Adds a routing tag to a request.
**********************************************l
public String addRouterTag(String data, String location) {
String outString;
outString = location+"~"+data;
return outString;

/**********************************************
* Sends the request to the server.
**********************************************l
public void sendRouterRequest(String ArgS) {
PrintStream dStream;
if(ServerNumber != 0)
ArgS = addRouterTag(ArgS, d~-stin ition);
try {
dStream = new PrintStream(Sock.getOutputStreamO);
dStream.pri~tlll(ArgS);
} catch(IOException e) {
System.out.println(e+" (Error sending Router Request)");
}
}




/**********************************************
* Starts a thread for this server object, to allow
* multiple servers to be cormected siml]lt~neo,,sly
*************~********************************1
public void startThreadO { 92

CA 02209265 1997-06-27

ServerThread tThread;
tThread = new ServerThread(cParent, ServerNumber);
tThread.startO;
}
}




93

CA 0220926~ 1997-06-27

import tcg.control.StringGrid;
import tcg.homeconnection.*;
import tcg.tools.*;
import java.awt.*;
import java.net.*;
import java.util.*;

I***********************************************
* Class: ResultPanel
* Written by: Brian Duncan
* Date:
* Purpose: This class en~apsu1~t~s a floating frame
* cont~ ing a String Grid and a scrolling Navigator
* ticker.
***********************************************/
class ResultPanel extends Frame {
Vector CatList;
StringGrid F~Pcl~ltT.ict
SeekFind cParent;
//These vectors keep track of the Originating servers,
//and Unique i~l~ntifi~rs for all records.
Vector ListServer, ListNumber;
//This thread controls the ad scrolling.
Thread tScroll;
NavigatorTicker AdScroll;
Button showDetail, close;
/***********************************************
* Constructor
***********************************************/
ResultPanel (String Title, SeekFind cArg) {
super(Title);
Vector Headers;
int Lengths~];
cParent = cArg;
CatList = cParent.CatPanel.getAllCategoriesO;
Headers = new VectorO;
int iLoop;
setResizable(false);
for(Enumeration e=CatList.elementsO; e.hasMoreElementsO; )
Headers ~ 1Fl~ment(((category) e.nextElementO).getHeaderO);
Res~lltr ict = new StringGrid(Headers);
AdScroll = new NavigatorTicker(this);
showDetail = new Button("Show Detail"); 9 4

CA 02209265 1997-06-27 .-

close = new Button("Close~');
//Start the thread for the ad scrolling, however,
//we don't need it yet, so suspend it.
tScroll = new Thread(AdScroll);
tScroll.startO;
tScroll cnspen~1o;
//Set widths here, when implemented.
ListServer = new VectorO;
ListNumber = new VectorO;
setLayout(null);
add("E~Psl.ltT,ict", Rpsllltr ict);
add("AdScroll", AdScroll);
add("showDetail", showDetail);
add("close", close);
}




public void reshape(int x, int y, int w, int h) {
super.reshape(x, y, w, h);
if( cParent.GlobalInd.getState0 ) {
p~s--ltT ictreshape(2,22,w,h-81);
AdScroll-showO;
AdScroll.reshape(l,h-65+2,w-2,30);
showDetail.reshape(w- 155,h-25,75,20);
close.reshape(w-75,h-25,75,20);
} else {
AdScroll.hideO;
~S~ltr.ict reshape(2~22~w4~h-92);
showDetail.reshape(w- 165,~ es~ltr .ict ci~loo~height+3o~7s~2o);
close.reshape(w-85,~esll1tT.ict ci7~o~height+3o~75~2o);
}
}




public boolean handleEvent(Event evt) {
if(evt.id = evt.WINDOW_DESTROY 11 (evt.target = close && evt.id = Event.MOUSE UP)) {
cParent.requestFocusO;
thic,hideO;
this.clearAI10;
return true;
}




return (super.handleEvent(evt));
}




public void atl-lrt~mc(Vector ArgV, int Argl) {
for(Enumeration e = ArgV.elements0;e.hasMoreFI~?mentc0;)
~ oSnltT ict ~ Tt~nn(bllilrlT ichng((vector) e neYtFl~ml~nt0, ArgI));
}




public void clearA110 {
ResultList.clearO; 9 5
ListServer.removeAllElementsO;

CA 02209265 1997-06-27
.


ListNumber.removeAllElementsO;
}




public void addAds(Vector ArgVI, Vector ArgV2) {
AdScroll.addMessages(ArgVI, ArgV2);
tScroll.resumeO;
}




public void stopAdsO {
tScroll Cl-spenflO;
}
public Vector bnil.lT icting(Vector ArgV, int ArgI) {
Category ThisCat;
String CurrNumber = "";
Vector vParsed, values;
String nextEI, ell, el2;
int iCounP0;
Enumeration e;
values = new VectorO;
e = ArgV.elementsO;
while( e.hasMoreFlPm,-~tcO ) {
nextEI = (String) e.nextElementO;
vParsed = Manipulation.split('=', nextEI);
ell = (String)vParsed.elementAt(0);
if ~vParsed.sizeO > I)
el2 = (String)vParsed.elementAt( I );
else
el2 = "";

if(ell .equals("listnum") ) {
CurrNumber = el2;
} else {
values ~ nlent(el2);
}




ListServer ~d~lFlement(new Integer(Argl));
ListNumber.addElement(CurrNumber);
return values;
}




public String getCurrentNumberO {
return (String) ListNumber.elementAt(ResultLict celect~r10);
}




public int getCurrentServer(int WhichOne) {
int tempInt;

CA 02209265 1997-06-27


tempInt= ((Integer) ListServer.elementAt(WhichOne)).intValueO;
return templnt;

public boolean action(Event evt, Object arg) {
if((evt.target inct~nceof StringGrid && "Double".equals(arg)) 11 arg.equals("Show Detail")) {
int ThisServer;
ThisServer = getCurrentServer(F~f~cnltT.ict celecte~lo);
cPar~nt initi~t~,Request("HOM", ThisServer);
return false;
} }

CA 0220926~ 1997-06-27 ._


import tcg.homeconnection.*;
import tcg.tools.*;
import java.awt.*;
import java.util.*;

I*************************************************
* Class: QueryPanel
* Written By: Brian Duncan
* Purpose: A list extension that holds selections chosen by
* the user. Contains methods that check to insure
* that a category puts only one line in it.
* Parameter: Count of max possible query lines.
*************************************************l
public class QueryPanel extends List {
//Holds all category names in the Query List
Vector CurrentCat;
SeekFind cParent;

I*********************************************
* Constructor
*********************************************l
public QueryPanel(Seek~ind ArgC) {
super(5, false);
cParent = ArgC;
//Initialize the vector for the categories
CurrentCat = new VectorO;
setRa~kground(Color.lightGray);
}




I**
* Adds a query line to the list. It first calls findQueryO
* to see if there is already a query from that category in
* there.
* Accepts two parameters: Category Name and Value vector.
* Takes all the values from the value vector and separates
* them with commas.
* (~see tcg.homeconnection.QueryPanel#findQuery
*l
public void addQuery(String Name, String Header, Vector Values) {
int IsThereOne;
IsThereOne = findQuery(Name);
if (IsThereOne > -1) { 9 8

CA 0220926~ 1997-06-27 ~_


/tRemove the category from the Query List
delItem(IsThereOne);
/tRemove the category from the vector.
CurrentCat.removeElementAt(IsThereOne);
}




if( !((String) V~1UPC elementAt(0)).equals("None") 1I V5lI11eS Ci7P() > I) {
addItem(Header+" = "+ Manipulationjoin(",",Values));
CurrentC~t ~d~Fl~oment(Name);
th ic celect(this.countItemso- I );
cParent.CatPanel.selectCategory((String)CurrentCat.elementAt(getSelt~c~ Tn(leY()));
}




I**
* If selected a query, set the category panel selection accordingly.
*t
public boolean handleEvent(Event evt) {
if (evt.id -- Event.LIST_SELECT) {
cParent.CatP~nel celectcategory((string)currentcat.elementAt(getselectedIndexo));
return false;
}




I**
* Checks to see if the category name passed already has an
* entry in the query panel.
*l
public int findQuery(String ArgS) {
int WhichOne = -1;
for(int iLoop = 0; iLoop < CurrentCat.size(); iLoop++) {
if( ((String)CurrentCat.elementAt(iLoop)).equals(ArgS)) {
~,VhichOne= iLoop;
break;
} }
return WhichOne;
}




/**
* Clears all query lines out of the query panel.
*/
public void clearA110 {
this.delItems(0,this.countItems()-l);
CurrentCat.removeAllElementsO;
} 99

- CA 0220926~ 1997-06-27 _


I**
* Clears currently selected query line out of the query panel.
*l
public void clearCurrent() {
int curltem;
curltem = this.getSelecte~llnd~YO;
if(curltem > - I )
clearItem(curltem);
}




/**
* Clears query line out of the query panel, based on Name.
*l
public void clearltem(String argS)
int whichItem;
whichltem = this.findQuery(argS);
if(whirhTtenn >-1)
clearItem(whichItem);
}




/**
* Clears query line out of the query panel, based on index.
*l
public void clearItem(int argI) {
CurrentCat.removeElementAt(argI);
this.delItem(argI);
/I Selected the one above it, if one, or the one below
Il it, if one
if(thic countlt~nnc() > o) {
if(argl-l >= O)
this.select(argI- I );
else
if(argI <= this.countItemsO)
this.select(argl);
}




**
* Builds a query string of all queries in the query panel,
* in a format that's can be passed to the server via cgi
* (sans the cgi header.) Parameter specifies whether to include
* all columns (LST), or to only include DynamicList and StaticList
* (PRO).
*l
100

CA 0220926~ 1997-06-27


public String getRequest(boolean ArgB) {
int iLoop;
String Request;
String Part;
String type;
int WhereEqual;
Request= "";
for(iLoop=0; iLoop < countItemsO; iLoop++) {
Il If ArgB is false, only use the columns that are StaticList or DynamicList.
if( !ArgB ) {
type = new String(
cParent.CatPanel.getCategory(((String)CurrentCat.elementAt(iLoop))).getTypeO );
if( !type.equals("DynamicList") && !type.equals("StaticList"))
contin~
}




Part = getItem(iLoop);
Part= Part.replace(',',~t');
Part= Part.replace('-','\t');
WhereEqual = Part.indexOf('=');
Part = ((String)CurrentCat.elementAt(iLoop))+"="+Part.substring(WhereEqual+2);
Request = Request + Part+"l";
}




if( Request.lengthO > ~ ) {
Request= Request cl~hstring(o~ Request.lengthO-1);
}




return Request;
}




101

CA 0220926~ 1997-06-27 .~-


import java.awt.*;
import java.lang.*;
import java.net.*;
import java.util.*;
I**
* NavigatorTicker by Ahmed Abdelhady <b>ahady(~idsc.gov.eg<b> <br>
A live Hypertext java applets.
* Modified by Brian Duncan:
* Now just a panel implementing runnable.
All Params are now either fixed or set with methods.
*l
public class NavigatorTicker extends Panel implements Runnable {
ResultPanel cParent;
/** index for the active message */
public int messageIndex=0;
/** TOtal no of messages */
public int messageCount=0;
/** The message to be displayed. */
public String message;
/** The messages Vector. */
public Vector msgs=new Vector();
/** The Font to be displayed. */
public Font messageF;
/** x-position of message. */
public int messageX;
/** y-position of message. */
public int messageY;
/** Length of the Active message. */
public int messageW = 0;
/** Messages Lengths Vector */
public Vector msgsW= new Vector();
/** URL to switch to */
public URL url_ = null;
/** Target URLs Vector */
public Vector msgsURL=new Vector();
/** How far to skip across the screen. */ 10 2

~ CA 0220926~ 1997-06-27 .-

int speed;
/** State of the applet. */
public boolean active = false;
/** The Text-color. */
public Color txtCo;
/** The Link-color. */
public Color linkCo;
/** The backgroundcolor. */
public Color bgCo;

/** The Size used to calc the Font. */
public Dimension lastS = new Dimension(l,l);
/** The offscreen image. */
Image im = null;
/** The offscreen Graphics context */
Graphics gr = null;
/* A flag that indicate mouse movement over the Applet */
boolean display_URL=false;
/* Mouse x Position */
int mouseX=0;

I**
* Initialize: Read Parameters
*
public NavigatorTicker (ResultPanel cArg) {
cParent = cArg;
// mcgc ~ Flement(new String("Microsoft's Home Page..."));
Il msgsURI, ~ArlFl~mPrlt(new String("http://www.microsoft.com"));
// mcgs ~rlF.lement(new String("Netscape's Home Page..."));
Il msgsURL.addElement(new String("http://www.netscape.com"));
// mcgc,~drlF.lement(new String("Yahoo (Search Engine Extraordinaire!)..."));
ll msgsURL.addElement(new String("http://www.yahoo.com"));
// mcgc ~F.lernent(new String("The Computer Group - USConnect..."));
ll msgsURL.addElement(new String("http://tcg.usconnect.com"));
// mcgc ~F.lement(new String("TCG's Home Link..."));
Il msgsURL.addElement(new String("http://176.16.9.12/homelink"));
speed= 10;
txtCo = Color.yellow;
linkCo = Color.red;
103

CA 0220926~ 1997-06-27 ~_


bgCo = new Color(0,0,128); l/Dark Blue
}




/* * Applet Info. */
public String getAppletlnfoO {
return "HadyTickerjava, V bl, 114196 by Ahmed Abdel-Hady extending the original ticker by Thomas
Wendt, http://www.uni-kassel.de/fb 1 6/ipm/mt/staff/thwendte.html";
}




* Create the image Parameters.
* Called, if just created or size has changed
*l
public void createParamsO {
ll Init some conct~ntc
int w = sizeO.width;
int h = sizeO.height;
lastS.width = w;
lastS.height = h;
ll dispose old buffer etc.
if (gr != null) { gr.fina!ize0; }
if (im != null) { im = null; }
ll Calc the font and positions. Message must fit applets area.
int refH = 14;
Font tf = new Font("TimesRoman", Font.BOLD, reflH);
setFont(tf);
FontMetrics tfm = getFontMetrics(tf);
int fh = tfrn.getHeightO;
fh = refH*(h-10)/fh;
messageF = new Font("TimesRoman", Font.BOLD, fh);
FontMetrics fm = getFontMetrics(messageF);
fh = fm.getHeight();
messageX = w;
messageY = ((h-fh) >> I)+fm.getAscent();
messageW = 0;

for(int i=0; icmessagecount;i++){
msgsW.addElement( new Integer(fm.stringWidth((String) msgs.elementAt(i))+14 ) );messageW+=fm.stringWidth((String) msgs.elementAt(i));
}




im = createImage(w, h);
gr= im.getGraphics();
}




I**
Painting the applet calls the overriding update to elimentate flicker
*l
public void paint(Graphics g) { update(g); }
/** Show the stuff */
public synchronized void update(Graphics g) { 104
if (messageCount > 0) {

CA 0220926~ 1997-06-27


1/ Recalc params, if something has changed
if ((size().height != lastS.height) 11 (sizeO.width != lastS.width)) { createParamsO; }
1/ fill area with bgcolor
gr.setColor(bgCo);
gr.fillRect(0,0,1astS.wi~th l~ct.~.height);
gr.drawRect(O,O,lastS.width- 1 ,lastS.height- I );
gr.drawRect(l,l,lastS.width-3,1astS.height-3);
gr.setColor(bgCo);
gr.draw3DRect(2,2,1astS.width-5, lastS.height-5, true);
gr.draw3DRect(3,3,1astS.width-7, lastS.height-7, true);
gr.clipRect(5,4,1astS.width- l O, lastS.height-8);
Il show status .. track mouse position..
if(display_URL) {
int currX=0,x=mouseX;
if( x > messageX ){ 11 clicking Nonempty area
x-=messageX; 11 compute displ~ment relative to start of the message
for(int i =O; i< messageCount; i++){
currX+=((Integer) msgsW.elementAt(i)).intValueO;
Il compare to acumulated widths to get clicked message index.
if ( x < currX ) { messageIndex=i; break;}
}
}




Il draw the text
gr.setColor(txtCo);
gr.setFont(messageF);
int disp=0;
for(int i=0;i<messageCount;i++){
if(i==messagelndex && display_URL) gr.setColor(linkCo);
else gr.setColor(txtCo);
gr.drawString((String) msgs.elementAt(i), messageX+disp, messageY); 11111111111111
disp+=((Integer) msgsW.elementAt(i)).intValueO;
//Added these two lines to test text separation.
if(i<messageCount-l) {
gr.setColor(new Color(128,0,0));
gr.fill3DRect(messageX+disp, 10, 10,12, true);
disp+=14;
}
}




Il finally show all together on the screen
g.drawImage(im,0,0,this);
}
}




/** calc next position of message and call repaint */
public synchronized void nextPos() {
Il decrement position
messageX -= speed; 10 5

CA 0220926~ 1997-06-27
.

ll and stay in the bounds
if ((messageX + messageW) < O) {
} meSSageX = lasts.width;
ll indirectly call update
repaint();
}




/** Run the loop. This method is called by class Thread. */
public void runO {
ll others might be more important
Thread.currentThreadO.setPriority(Thread.MIN_PRIORITY);
while (true) {
ll do the job
nextPosO;
ll pause
try {Thread.sleep(lOO);}
catch (InterruptedException e){ }
}
}




/* * Switch to url, if url is given. */
public boolean mouseUp(Event evt, int x, int Y) {
try { url_ = new URL((String)msgsURL.elementAt(messageIndex)); }
catch (Exception e) { url_= null; }
if ( url_ != null) { cParent.cParent.getAppletContextO.showDocument( url~ (String)
msgs.elementAt(messageIndex)); } ll might not work with some early browsers
return true;
}




public boolean mouseEnter(Event evt, int x, int Y) {
display_URL = true;
retum true;
}




public boolean mouseExit(Event evt, int x, int Y) {
display_URL = false;
return true;
}




public boolean mouseMove(Event evt, int x, int Y) {
mouseX=x;
return true;
}




public void addMessages( Vector ArgV 1, Vector ArgV2 ) {
msgsW.removeAllElementsO;
msgs = ArgVI; 106

CA 02209265 l997-06-27


msgsURL = ArgV2;
messageCount = ArgVl.sizeO;
createParamsO;
}




107

CA 0220926~ 1997-06-27


import java.awt.*;
import tcg.tools.*;
import tcg.homeconnection.*;

/***********************************************
* Clacs: AboutPanel
* Written by: Brian Duncan
* Date:
* Purpose: To display a Sek&Find-specific about box with
* the QnimQt~d image sequence displayed.
***********************************************l
public class AboutPanel extends Frame {
SeekFind cParent;
Button bOk;
ImagePanel imagePanel;

/***********************************************
* Constructor
***********************************************/
AboutPanel (String title, SeekFind cArg) {
super(title);
/l String line = "";
ll //Build the 'line' string;
ll for(int iLoop=0;iLoop<30;iLoop++)
Il line+= '\304';
cParent = cArg;
thic cetT ~yout(null);
this.setResizable(false);
bOk = new Button("OK");
imagePanel = new ImagePanel(136,74,this);
imagePanel.setLayout(new FlowLayout(FlowLayout.CENTER,15,15));
add("OK", bOk);
add("Image",imagePanel);
imagePanel.reshape(82,40,136,74);
bOk.reshape(140,225,30,20);


I***********************************************
* Allow the frame to close normally
***********************************************l
public boolean handleEvent(Event evt) {
if(evt.id = evt.WINDOW_DESTROY 11 evt.arg.equals("OK")) {
this.hide();
return true; 1 0 8

CA 0220926~ 1997-06-27
, : ' .

return (super.handleEvent(evt));
}




I***********************************************
* Paint the image and the text
********************4*************/
public void paint(Graphics g) {
int fLeft, frop, fHeight, fWidth, fCurrentY;
//Need three different fonts for various text
Font f= new Font("TimesRoman", Font.PLAlN, 12);
Font f2 = new Font("TimesRoman", Font.BOLD, 12);
Font f3 = new Font("TimesRoman", Font.PLAIN, 10);
String versionString;
fWidth = getFontMetrics(f).stringWidth("Copyright (c) 1996 The Computer Group");fLeft= (300 - fWidth)/2;
fTop= 105;
fHeight = getFontMetrics(f2).getHeightO;
versionString= "Version "+cParent.getVersion0;
g.setFont(f2);
g.drawString(versionString,78, fTop);
g .setColor(Color.black);
g.fillRect(fLeft,fTop+4,fWidth,3);
g.setFont(f3);
fCurrentY = fTop+fHeight+6;
g.drawString("Copyright (c) 1996 The Computer Group", fLeft,fCurrentY);
fCurrentY += getFontMetrics(f3).getHeightO;
g.drawString("All Rights Reserved.", fLeft, fCurrentY);
g.setFont(f);
g.drawLine(fLeft,fCurrentY+4,fLeft+fWidth,fCurrentY+4);
fCurrentY += fHeight+3;
g.drawString("Patent Pending", fLeft, fCurrentY);
g.drawLine(fLeft,fCurrentY+4,fLeft+fWidth,fCurrentY+4);
fCurrentY += fHeight+2;
g.setFont(f3);
g.drawString("Written by Brian Duncan", fLeft, fCurrentY);
fCurrentY += fHeight-2;
g.drawString("Data grid written by Curtis Keisler", fLeft, fCurrentY);
}
.




class ImagePanel extends Panel {
AboutPanel cParent;
public ImagePanel(int X, int Y, AboutPanel argC) {
cParent= argC;
reshape(0,0,X,Y);
} 109

CA 02209265 1997-06-27
.;

public void paint(Graphics g) {
cParent.cPar~nt !~pl~ch ~lrawBaseImage(this~getGraphicso~ 0, 0, 135, 73);
for(int iLoop=0;iLoop < 17;iLoop~)
cParent.cParent.Splash.drawOverlay(iLoop, this.getGraphicsO, 0, 0, 135, 73);
} }




110

CA 0220926~ 1997-06-27 _

package tcg.control;
/l This example is from the book _Java in a Nutshell_ by David Flanagan.
l/ Written by David Flanagan. Copyright (c) 1996 O'Reilly & ~Csori~tes
// You may study, use, modify, and distribute this example for any purpose.
// This example is provided WITHOUT WARRANTY either expressed or implied.
import java.awt.*;
import java.util.~;
public class MllltiT ineT ~hel extends Canvas {
public static final int LEFT = 0; // ~ nment conct~ntc
public static final int CENTER= I;
public static final int RIGHT = 2;
protected String[] lines; // The lines of text to display
~" ot~ ~,t~,d int num lines; // The number of lines
protected int margin width; // Left and right margins
protected int margin height; // Top and bottom margins
pl ~ d int line height; ll Total height of the font
protected int line_ascent; ll Font height above baseline
protected int[] line widths; /t How wide each line is
protected int max width; l/ The width of the widest line
protected int alignment = LEFT; ll The ~lignmPnt of the text.
ll This method breaks a specified label up into an array of lines.
// It uses the StringTokenizer utility class.
protected void newLabel(String label) {
StringTokenizer t = new StringTokenizer(label, "\n");
num_lines = t.countTokensO;
lines = new String[num lines];
line_widths = new int[num_lines];
for(int i = 0; i < num_lines; it t) lines[i] = t.nextTokenO;
}




// This method figures out how the font is, and how wide each
// line of the label is, and how wide the widest line is.
protected void measureO {
FontMetrics fm = this.getFontMetrics(this.getFontO);
// If we don't have font metrics yet, just retum.
if (fm = null) retum;
line_height= fm.getHeightO;
line_ascent = fm.getAscentO;
max_width = 0;
for(int i = 0; i < num lines; i~) {
line_widths[i] = fm.stringWidth(lines[i]);
if (line_widths[i] > max_width) max_width = line_widths[i];
}




// Here are four versions of the cosntrutor.
// Break the label up into separate lines, and save the other info.
public MultiLineLabel(String label, int margin_width, int margin_height,
int ~1 ignm~nt) {
newLabel(label); 11 1

CA 02209265 1997-06-27 ~_

this.margin_width = margin_width;
this.margin_heig_t = margin_height;
thic ~lignment = alignment;
}
public MultiLineLabeltString label, int margin_width, int margin_height) {
this(label, margin-widt-h-~ margin_height, LEFl~);
}
public MultiT ineT ~hel(string label, int alignment) {
this(label, 1O, lO, alignment);
}




public MultiT.ineT ~bel(String label) {
this(label, 10, 10, LEFT);
}




// Methods to set the various aLLI ibut~s of the CG. . .l~o
public void setT ~ I(String label) {
newLabel(label);
IllLaSUl ~,0;
repaintO;
}




public void setFont(Font f) {
super.setFont(f);
measureO;
repaintO;
}




public void setFol~ol~nd(Color c) {
super.setFol~ d(c);
repaintO;
}




public void setAlignment(int a) { alignment = a; repaintO; }
public void setMarginWidth(int mw) { margin_width = mw; repaintO; }
public void setMarginHeight(int mh~ { margin_height = mh; repaintO; }
public int getAlignmentO { return alignmpnt; }
public int getMarginWidthO { return margin_width; }
public int getMarginHeightO { return margin_height; }
// This method is invoked after our Canvas is first created
// but before it can actually be displayed. After we've
// invoked our superclass's addNotifyO method, we have font
// metrics and can succ~ossfil11y call measureO to figure out
// how big the label is.
public void addNotifyO { super.addNotifyO; measureO; }
/I This method is called by a layout manager when it wants to
Il know how big we'd like to be.
public Dimension preferredSizeO {
return new Dimension(max width + 2*margin_width,
num_lines * line_height + 2*margin_height);
}




Il This method is called when the layout manager wants to know
Il the bare minimum amount of space we need to get by.
public Dimension minimllm!~izeO {
return new Dimension(max_width, num_lines * line_height);
112

- CA 0220926~ l997-06-27 --



Il This method draws the label (applets use the same method).
Il Note that it handles the margins and the alignment, but that
Il it doesn't have to worry about the color or font--the superclass
Il takes care of setting those in the Graphics object we're passed.
public void paint(Graphics g) {
int x, y;
Dirnension d = this.sizeO;
y = line_ascent + (d.height - num_lines * line_height)/2;
for(int i - O; i < num_lines; i++, y += line_height) {
switch(alignment) {
case LEFT:
x = margin_width; break;
case CENTER:
default:
x = (d.width - line_widths[i])/2; break;
case RIGHT:
x= d.width - margin_width - line_widths[i]; break;
}




g.drawString(lines[i], x, y);
}
}




113

CA 0220926~ 1997-06-27 ,-
', ' "

package tcg.control;
import java.awt.*;
irnport java.util.*;

I***********************************************************
Java StringGrid Class
Copyright 1996 by Curtis Keisler
Modified by Brian Duncan for use in SeekFind.
***********************************************************/
public class StringGrid extends Panel {
Il Selection bar color
public static final Color selçctionR~rcolor = new Color(0,0,127);
protected
int 1I The number of pixels to use for the row height
rowHeight= 10,
Il Used in text drawString as the offset for the row
rowAscent,
Il The current row
currentRow = 0,
// The left most column
leftColumn = 0,
// The last sorted column
lastSortCol = -1,
// The currently selected row
selecteA~ow = -1;
protected
Vector 1I Vectors of Strings for the columns. The vector need
// need not be valid or defined. If so, blanks just
// display in the "holesn.
row = new Vector(6,6),
// The original data
data = new Vector(6,6),
// Strings with the text for the column headings.
columnHeading = new Vector(6,6),
// Integers for the order of the columns since colurnns can
// be moved by the user, the physical order of the colurnns
114

- CA 0220926~ 1997-06-27 -
.

ll in the vector may be different than the logical, viewed
ll order of the colums.
columnOrder= new Vector(6,6),
Il Integers con~ining the current column widths. Initially
ll set to the width of the header.
columnWidth = new Vector(6,6);
protected
Scrollbar ll The scrollbars on the grid
horizScrollbar = new Scrollbar(Scrollbar.HORIZONTAL, l ,0,0,0),
vertScrollbar = new Scrollbar(Scrollbar.VERTICAL, l ,0,0,0);
protected~tatic final int columnWidthPad = 6,
columnHeightPad = 4;~ont gridFont = new Font("Dialog",Font.PLAIN,l0);

1**********************************************************1
public StringGridO
l*
PROCEDURE
public StringGridO
PURPOSE
StringGrid class constructor
{ */
superO;
setLayout(new BorderLayout0);
ll Install the scroll bars
horizScrollbar.setLineIncrement( l );
vertScrollbar cetT.ineTnrrement(l);
horizScrollbar.setPageIncrement( I );
vertScrollbar.setPageIncrement(l);
add("South",horizScrollbar);
add("East",vertScrollbar);
ll Set the default font
setFont(gridFont);
ll Get the needed height of each row
rowHeight = getFontMetrics(gridFont).getMaxAscentO+
getFontMetrics(gridFont).getMaxDescentO;
rowAscent = getFontMetrics(gridFont).getMaxAscentO;
} ll StringGrid

1**********************************************************1
public boolean handleEvent(Event e)
/* 115

_. CA 0220926~ l997-06-27

PROCEDURE
public boolean handleEvent(Event e)
PURPOSE
To handle the horizontal and vertical scroll bar events.
*l
{




boolean handled = false;
// Clicked the horizontal scroll bar
if (e.target = horizScrollbar)
switch(e.id) {
case Event.SCROLL_LrNE_UP:
case Event.SCROLL_LINE_DOWN:
case Event.SCROLL_PAGE_UP:
case Event.SCROLL_PAGE_DOWN:
case Event.SCROLL_ABSOLUTE:
leftColumn = ((Integer)e.arg).intValue();
if (leftColumn < 0)
leftColumn = 0;
else if (leftColumn > columnHea~ing Ci7~0 _1)
leftColumn = columnHe~ling Ci7f'() -1;
repaintO;
handled = true;
break;
}




else if (e.target = vertScrollbar)
switch(e.id) {
case Event.SCROLL _ LrNE_UP:
case Event.SCROLL_L~NE_DOWN:
case Event.SCROLL_PAGE_UP:
case Event.SCROLL_PAGE_DOWN:
case Event.SCROLL_ABSOLUTE:
currentRow = ((Integer)e.arg).intValueO;
if (currentRow < 0)
currentRow = 0;
else if (currentRow > row sizeO - I)
currentRow=row.sizeO- I;
repaintO;
handled = true;
break;
}




if (handled)
return true;
else
return super.handleEvent(e);
} // handleEvent

/**********************************************************/
public boolean mouseDown(Event evt, int mx, int my)
I*
*/
{ 116

CA 0220926~ 1997-06-27 -


int x, ll Used to find the column
r, ll The clicked row
col, ll Search column
width, ll The maximum width
height; ll The bottom of the headings
Integer cwi; ll Column width
boolean done = false; ll Loop flag
ll Compute the height of the column headings
height = rowHeight + columnHeightPad;
width = sizeO.width - vertScrollbar.sizeO.width;
ll If the mouse was clicked within the column headings
if ((my <= height) && (mx <= width) ) {
// Determine the column and sort on it.
// Start at the left side
x=O;
// Start with the left column
col = leftColumn;
done = false;
while (!done) {
ll Are we looking in a valid column?
if ((col < columnWidth.sizeO) && (x < width)) {
ll Get the current column width
cwi = (Integer)columnWidth.elementAt(col);
ll Is the mouse on this column?
if (mx <= x + cwi.intValueO + columnWidthPad) {
ll Draw the column heading depressed
ll so that the user knows that something
ll is happening.
drawColumnHeading(getGraphicsO,x,col,false);
ll Then sort the column
sortColumn(col);
done = true;
} else {
col++;
x = x + cwi.intValue() + columnWidthPad;
}




} else
done = true;
}




return true;
ll Otherwise, see if we clicked on a row then select it
} else
//If we double clicked, pass the event up to the parent.
if ((my < sizeO.height - horizScrollbar.size().height) &&
(mx < width) && (my > height) ) {
117

CA 0220926~ 1997-06-27 --

if(evt.clickCount>l) {
getParentO.postEvent(new Event(this,Event.ACTlON_EVENT,"Double"));
return true;
} else {
1/ Compute the selected row
selectedRow = currentRow + (my - height) / height;
Il If greater that the max row then it is the max row
if (selectedRow > row.size()- I )
selectedRow = row.sizeO-I;
Il Redraw to show the selected row
repaint(0);
return true;
}




} else {
return false;
} 11 mouseDown

1**********************************************************1
public void setColumnHeadings(Vector pColumnHeading)
PROCEDURE
public void setColumnHeadings(Vector pColumnHeading)
PURPOSE
To set the column headings to the given vector of strings.
The widths of the columns are initialized to the width of
the headings. Because of this, the procedure should be
called before adding and rows to the ~rid.
INPUT PARAMETERS
pColumnHeadings - The Vector of strings containing the
column headings.

{ *l
FontMetrics fm = getFontMetrics(gridFont);
Il Set the new columns to the passed in ones
columnHeading = pColumnHeading;
1/ Compute the column widths based on the column headings
computeColumnWidthsO;
Il Set the horizontal scroll bar
horizScrollbar.setValues(O,l,O,columnHP~fling.ci7,~0 1);
} 11 setColumnHeadings

1**********************************************************1
public void computeColumnWidths() 118

CA 0220926~ 1997-06-27 ,-
i, ..

/*
PROCEDURE
public void computeColumnWidthsO
PURPOSE
To compute the column widths based soley on the widths of
the column headings.
{ *l
FontMetrics fm = getFontMetrics(gridFont);
Il Clear out any old column widths
columnWidth.removeAllElementsO;
Il Loop through each and compute the column widths
for (int i = 0; i < COlumnHP?~ neci7f~o;i++)
Il Compute the width and insert it into the
Il column widths vector.
columnWiflth ~ Fl~ment(new Integer(fm.stringWidth((String)columnHeading.elementAt(i))));
} 11 computeColumnWidths

1**********************************************************1
public void addColumnHeading(String heading)
*l
{




FontMetrics fm;
fm = getFontMetrics(gridFont);
Il Append the passed in column heading
columnHe If line ~ IFIement(heading);
Il Compute the width and insert it into the column
Il width vector.
columnWi-lth ~ F~lement(new Integer(fm.stringWidth(heading)));
Il Set the horizontal scroll bar
horizScrollbar.setValues(horizScrollbar.getValue(), I,
0,columnHeading.size()-l );
} 11 addColumnHeading

/***********************************$**********************/
public boolean addItem(Vector item)
* *
{ int cw, 11 Column width
i, 11 Loop counter
p; 11 Tab position indicator
Integer cwi; 11 Integer column width
String s; 119

. CA 0220926~ 1997-06-27 ,-
,

Vector newRow = new Vector(6,6);
l/ Pull out each column
for (i = O; i < columnHe~ing ci7~0;i++)
newRow.addElement(item.elementAt(i));
row ad-lFlement(newRow);
if (columnWidth != null) {
for (i = O; i < columnWidth.size(); i++) {
cwi = (Integer)columnWidth.elementAt(i);
if (i < newRow.size()) {
s = (String)newRow.elementAt(i);
cw = getFontMetrics(gridFont).stringWidth(s);
if (cw > cwi.intValueO)
columnWi-lth cetFl~mentAt(new Integer(cw),i);
}
}




Il Set the veritcal scroll bar
vertScrollbar.setValues(vertScrollbar.getValueO, I ,O,row.sizeO- I );
if(sizeO.height > (row.sizeO*rowHeight))
repaintO;
return true;
} ll addItem
//Add multiple rows, parm is a vector of vectors
public void addltems(Vector item) (
for(int iLoop = O;iLoop < iS~m Ci7f'0; iLoop++)
addltem((Vector) item.elementAt(iLoop));
}




public int countItemsO {
return row.sizeO;
}




public void clearO {
row.removeAllElements();
}




public void removeColumnHeadings() {
clear();
columnHeading.removeAllElements();
}




public int selectedO {
return selectedRow;

}




/*****$****************************************************/
private void reverseOrderO 120

CA 0220926~ 1997-06-27 ~-

PURPOSE
Reverses the order of the rows. This simulates sorting
in the opposite order.
{ */
int i,mid,max;
Vector v;
max = row.sizeO ~ I;
mid = max / 2;
for (i = 0; i <= mid; i++)
// Don't swap the same row!
ll Swap the rows
v = (Vector)row.elementAt(i);
row ~etF.lom~nt~t(row.elementAt(max- i),i);
row cetF.l~m~nt~t(v,max - i);
}




} ll reverseOrder

1**********************************************************1
public void sortColumn(int sortCol)
PROCEDURE
public void sortColumn(int sortCol)
PURPOSE
To sort the given column. If the given column was the last
one to sort on, then the sort will be in the opposite
direction of the previous sort i.e. it will toggle between
~cen~ing and descending order.
INPUT PARAMETERS
sortCol - The column on which to sort.
{




// If we are not sorting on the same column as the last
// time, then start in ascending order.
if (sortCol--lastSortCol)
reverseOrder();
else
// Sort the column
quickSort(sortCol,O,row sizeO-I);
// Start at the top of the list
currentRow = 0;
// Unselect the selected row
selectedRow = - l;
121

CA 0220926~ 1997-06-27


// Set the vertical scroll bar back to 0
vertScrollbar.setValue(0);
// Save the col number for next time
lastSortCol = sortCol;
// Refresh the screen
repaint(0);
11 sortColumn

1**********************************************************1
private int compare(int rl, String r2, int c)

PROCEDURE
public boolean compare(int rl, int r2, int c);
PURPOSE
To compare the two rows for the given column using the
columnType indicator. If a column type indicator is not
defined for the column, the col..?al ison is done on a string
basis.
INPUT PARAMETERS
rl - The row number of the row in the row vector to
compare against r2.
r2 - The row number rl is compared against.
c - The column in the row to be compared.
RETURNS
<Oifrl <r2
0 if rl = r2
>Oifrl>r2

{ */
int comparison = 0; /I The outcome of the comparison
Il (assumes everything is equal)
Vector rv; 11 The row vector.

String src l;
// Get the first row
rv = (Vector)row .elementAt(r I );
// Get the column in the first row
srcl = (String)rv.elementAt(c);
comparison = srcl.compareTo(r2);
return comparison;
} // Compare

/**********************************************************/
private void quickSort(int sortCol, int p, int r) 12 2

CA 0220926~ 1997-06-27


PROCEDURE
private void quickSort(int sortCol, int p, int r)
PURPOSE
Implements the famous "Quick Sort" algorithm for sorting
the rows on a given column. See the compare function
INPUT PARAMETERS
sortCol - The column on which to sort.
p - The first row number in the row Vector to be sorted.
r - The last row number in the row Vector to be sorted.
*l
{




if(p<r) {
int q = partition(sortCol,p,r);
quickSort(sortCol,p,q);
quickSort(sortCol,q+ l ,r);
}




} ll quickSort

1**********************************************************1
private int partition(int sortCol, int p, int r)
I*
PROCEDURE
private int partition(int sortCol, int p, int r, int dt)
PURPOSE
Partitions the array for a quicksort.
INPUT PARAMETERS
sortCol - The column on which to sort.
p - The begining of the partition search.
r - The end of the partition search.
dt - The data type of the column.
RETURN
The row where all rows above are less than the rows below.
*l
{




int i = p - l
j=r+ I;
Vector v = (Vector)row.elementAt(p);;
String x = (String)v.elementAt(sortCol);
while (true) {
do
j__;
while ((compare(j,x,sortCol) > 0));
do
i++;
while (compare(i,x,sortCol) < 0); 123

. CA 0220926~ 1997-06-27


if (i <i) {
ll Swap the rows
v = (Vector)row.elementAt(i);
row.setElementAt(row.elementAt(j),i);
row.setElementAt(v,j);
} else
return j;
}




} ll partition

1**********************************************************1
public void drawCell(Graphics g, int x, int y, int width,
int drawCol, int drawRow)
/*
PURPOSE
To draw the given cell at the given location on the given
graphics object.
*l
{




Graphics cg; // Clipped graphics cell
Vector v; // Temporary vector used to get the cell
String s; // Contents of the cell
int sw; // The drawing text width of the cell
// used to compute ~lignm~nt offsets.
ll If this is a selected row then draw the selection bar
if (drawRow = selectedRow) {
g.setColor(selectionBarColor);
g.fillRect(x,y,width,rowHeight+columnHeightPad-l);
}




ll Draw the grid box for the cell
ll Draw the left side of the grid line
g.setColor(Color.gray);
g.drawLine(x,y,x,y + rowHeight + columnHeightPad-l);
g.drawLine(x,y + rowHeight + columnHeightPad-l,
x + width-l,y + rowHeight + columnHeightPad-l);
if(drawCol--columnWidth.size()- l)
g.drawLine(x+width- l ,y,x+width- l,
y + rowHeight + columnHeightPad- l );
ll Draw the left side on the left most column
if (x == 0)
g.drawLine(x,y,x,y + rowHeight + columnHeightPad-l);
ll Use a clipped graphics to draw the text
cg = g.createO;
cg.setFont(gridFont);
cg.clipRect(x+l,y+l ,width-2,rowHeight+columnHeightPad-2);
if (row != null) {
ll Get the current row of vectors
v = (Vector)row.elementAt(drawRow);
124

CA 0220926~ 1997-06-27 ~_
~. '
.

if (v != null) {
Il Is there a value for the column we are on?
if (drawCol < v.size()) {
Il Get the value
s = (String)v.elementAt(drawCol);
Il If it is valid, then draw the string
if (s != null) {
Il Get the string width
sw = cg.getFontMetrics().stringWidth(s);
Il Set the color to black non selected
Il or white if selected
if (drawRow = selectedRow)
cg.setColor(Color.white);
else
cg.setColor(Color.black);
cg.drawString(s,
x+columnWidthPad/2,
y+rowAscent+columnHeightPad/2- 1 );
}
}
}




} 11 drawCell

1**********************************************************1
protected void drawColumnHeading(Graphics g, int x,
int drawCol, boolean raised)
I*
PROCEDURE
protected void drawColumn(Graphics g, int x, int drawCol,
boolean raised)
PURPOSE
To draw the given column, starting at the given x position
on the given graphics object.
rNPUT PARAMETERS
g - The graphics object on which to draw the column.
x - The x position where the column should be drawn.
drawCol - The index of the column to draw
(0 - columnH~ing ci7e()-l)
raised - True if the heading is raised, false if it is
lowered.
*l
{




int w,y,h,shift;
String s;
y=O;
h = rowHeight + columnHeightPad;
1/ Get the column width 12 5

CA 0220926~ 1997-06-27


w = ((Integer)columnWidth.elementAt(drawCol)).intVàiueO
+ columnWidthPad;
Il Draw the raised 3D header
g.setColor(Color.lightGray);
g.fillRect(x, y, w, h);
if (raised) { I/ If raised
shift= 0;
g.setColor(Color.white);
g.drawLine(x + I, y + 1, x + I, y + h - 3);11 Left
g.drawLine(x+2,y+ I,x+w-2,y+ I);//Top
g.setColor(Color.gray);
g.drawLine(x+ I,y+h-2,x+w- I,y+h-2);//Bottom
g.drawLine(x + w - I, y + h - 3, x + w - I, y + I); // Right Side
} else { /l otherwise depress
shift= I;
g.setColor(Color.gray);
g.drawLine(x + I, y + I, x + 1, y + h - 3);11 Left
g.drawLine(x + 2, y + I, x + w - 2, y + 1);1/ Top
g.setColor(Color.white);
g.drawLine(x+ I,y+h-2,x+w- I,y+h-2);//Bottom
g.drawLine(x + w - I, y + h - 3, x + w - I, y + I); // Right Side
}




/I Draw a black rectangle around this
g.setColor(Color.black);
g.drawLine(x,y,x+w- I ,y);
g.drawLine(x,y+h- I ,x+w- I ,y+h- I );
g.drawLine(x,y,x,y+h- I );
// If the last column then draw the right side
if(drawCol==columnWidth.size()- I)
g.drawLine(x+w- I ,y,x+w- 1 ,y+h- I );
// Draw the column heading text
g.setColor(Color.black);
g.setFont(gridFont);
s = (String)columnHeading.elementAt(drawCol);
if (s != null)
g.drawString(s,x+columnWidthPad/2+shift,y+rowAscent+columnHeightPad/2+shift-l);
else
g.drawString("BAD ! ",x+columnWidthPad/2+shift,y+rowAscent+columnHeightPad/2+shift- 1 );
I/ drawColumnHeading

1**********************************************************/
protected void drawColumn(Graphics g, int x, int drawCol)
/*
PROCEDURE
protected void drawColumn(Graphics g, int x, int drawCol)
PURPOSE
To draw the given column, starting at the given x position
on the given graphics object. 126

CA 0220926~ 1997-06-27 ~-


rNPUT PARAMETERS
g - The graphics object on which to draw the column.
x - The x position where the column should be drawn.
drawCol - The index of the column to draw
(O - COlumnHea~lillg Ci7PO-I)
*l
int width, ll The width of the table minus the
Il vertical scrollbar width.
y, ll The current y position
height, ll The height of the table minus the
Il horizontal scrollbar height.
drawRow; ll The current drawing row
String s; ll Temporary string
Il Compute the drawing room
height = sizeO.height - horizScrollbar.sizeO.height;
Il Start at the top
y=O;
Il Ensure that the column is in the correct range
if ( (drawCol >= 0) && (drawCol < columnWidth.sizeO)) {
Il Get the column width
width = ((Integer)columnWidth.elementAt(drawCol)).intValueO
+ columnWidthPad;
Il Clear the background
g.setFont(gridFont);
g.setColor(Color.white);
g.fillRect(x,rowHeight+columnHeightPad,width,height);
drawColumnHeading(g,x,drawCol,true);
Il Move to the next row
y = y + rowHeight + columnHeightPad;
Il Loop through each row until we are at the bottom of the
Il screen or out of rows.
drawRow = currentRow;
while ((drawRow < row.sizeO) && (y <= height)) {
drawCell(g,x,y,width,drawCol,drawRow);
Il Advance to the next row
y = y + rowHeight + columnHeightPad;
drawRow++;

} ll drawColumn
127

_ CA 0220926~ 1997-06-27


1**********************************************************1
public void update(Graphics g)
PROCEDURE
public void update(Graphics g)
PURPOSE
To override the default update so that screen is not
erased before the new one is drawn.
{ *l
paint(g);
} 1/ update

/**********************************************************/
public void paint(Graphics g)
PROCEDURE
public void paint(Graphics g)
PURPOSE
To display the grid. If the column headings and alignment
have not been specified, then nothing is displayed.
lNPUT PARAMETERS
g- The graphics object on which to draw.
{ */
int i, // Loop counters
x, 1/ The current x position
width, 11 The width of the table
height, 11 The height of the table minus the
Il horizontal scrollbar height.
drawRow, 11 The current drawing row
drawCol; 1/ The current drawing column
Image image; // Temporary drawing image so that redraws
// are done cleanly.
Graphics ig; // Image's graphics object
image = createImage(sizeO.width,size().height);
ig= image.getGraphicsO;
ig.setFont(gridFont);
Il If there are column headings and alignments then draw
Il the grid, otherwise, don't bother.
if ( (columnHeading != null)) {
Il Start or, the left side
x = O;
Il Loop through each column, until we have reached the
Il right side of the screen or we have run out of
Il columns. 12 8

CA 0220926~ 1997-06-27 _~


i = leftColumn;
while ((i < columnHe~ling ':i7~'0) && (x < sizeO.width)) {
drawColumn(ig,x,i);
ll Advance to the next column
width = ((Integer)columnWidth.elementAt(i)).intValueO
+ columnWidthPad;
x += width;
i++;
}




ll Now, draw the new screen.
g.drawImage(image,O,O,null);
}




ll Compute vertical number of columns and adjust
ll the horizontal scroll bar accordingly.
height = sizeQheight - horizScrollbar.sizeO.height -
(rowHeight + columnHeightPad);height = Math.round(height / (rowHeight + columnHeightPad));
vertScrollbar ~etT inçTncrement(l );
vertScrollbar.setPageIncrement(height);
} ll paint
} ll StringGrid




129

CA 0220926~ l997-06-27
.' ' i ~.~,

package tcg.control;
import java.awt.TextField;
import java.awt.Color;

/*******************************************************
* Class: StatusBox
* Written by: Brian Duncan
* Date:
* Purpose: Extends the TextField class. It is used as a status
* window to display the current operation.
*




* The default message is 'Ready'.
*******************************************************/
public class StatusBox extends TextField {

/*******************************************************
* Constructor for StatusBox class. This one allows for
* a default of "Ready"
*******************************************************/
public StatusBoxO {
this("Ready");
}




/*******************************************************
* Constructor for StatusBox class. Like other one, except that
* it allows a parameter for the initial message.
*******************************************************/
public StatusBox(String sArg) {
super(sArg, 30);
this.setBackground(Color.lightGray);
this.setForeground(Color.blue);
thic cetF-lit~ble(false);




/*******************************************************
* Sets the statusbox message.
*******************************************************/
public void set~t~t lc(String sArg) {
this .setText(sArg);
}




130

CA 0220926~ 1997-06-27 _

package tcg.control;

import java.awt.*;

/*********************************************************
* Class: ErrorDialog
* Written by: Brian Duncan
* Date:
* Purpose: This class simulates a popup messagebox.
*********************************************************/
public class ErrorDialog extends Frame {

protected Button button;
protected MnltiT inel ~hel label;
int lines;

I*******************************************************
* Constructor
*******************************************************/
public ErrorDialog(String title, String message) {
super(title);
thic cetT ~yout(new BorderLayout(5, 5));
label = new MultiLineLabel(message,30,30, Label.CENTER);
this.add("Center", label);

/lUsing a separate panel to center the button horizontally,
llbut keep it at the bottom of the frame.
Panel p = new PanelO;
p.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
button = new Button("OK");
p.add(button);
this.add("South", p);
Il Resi~ the window to the preferred size of its components
this.pack();
}




I*******************************************************
* Kill the window when the button is clicked
*******************************************************l
public boolean action(Event e, Object arg) {
if(e.target == button) {
this.hide();
((Component)getParentO).requestFocusO;
this.disposeO;
return true; 131

CA 02209265 1997-06-27 ~_


else return false;




132

- CA 0220926~ 1997-06-27 ~_


package tcg.control;

import java.awt.*;

I*********************************************************
* Class: ErrorDialog
* Written by: Brian Duncan
* Date:
* Purpose: This class simulates a popup messagebox.
*********************************************************/
public class ErrorDialog extends Frame {

protected Button button;
protected MnltiT in~oT ~bel label;
int lines;

I*******************************************************
* Constructor
*******************************************************/
public ErrorDialog(String title, String message) {
super(title);
this.setLayout(new BorderLayout(5, 5));
label = new MultiLineLabel(message,30,30, Label.CENTER);
this.add("Center", label);

//Using a separate panel to center the button horizontally,
/Ibut keep it at the bottom of the frame.
Panel p = new PanelO;
p.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
button = new Button("OK");
p.add(button);
this.add("South", p);
Il Resize the window to the preferred size of its components
this.packO;
}




I*******************************************************
* Kill the window when the button is clicked
*******************************************************/
public boolean action(Event e, Object arg) {
if(e.target == button) {
this.hide();
((Component)getParentO).requestFocusO;
this.dispose(); 13 3
return true;

CA 0 2 2 0 9 2 6 5 1 9 9 7 - 0 6 - 2 7


else return false;




134

CA 0220926~ 1997-06-27 --
t

package tcg.homeconnection;
import java.awt.*;
import java.util.*;

I*******************************************************
* Class: ValueSingle
* Written by: Brian Duncan
* Date:
* Purpose: This class extends ValuePanel (Panel) to provide
* a singleLineEdit panel.
*******************************************************l
public class ValueSingle extends ValuePanel {
TextField Valuel;

I*******************************************************
* Constructor: Parameter is Category Name
*******************************************************/
public ValueSingle(String argS) {
name = argS;
Valuel = new TextField(20);
Valuel cetRarkpround(color.white);
setR~rl~p.round(Color.lightGray);
add("Valuel", Valuel);
}




I*******************************************************
* Returns the value of the SLE. in a vector. If empty,
* returns "None" in the vector.
*******************************************************l
public Vector getValuesO {
Vector Values = new Vector(l);
if(Value I .getTextO.trimO.lengthO == 0) {
V~ s ~ Flrment("None");
} else {
Vall-es ad~F.lement(Valuel.getText());
return Values;
}




/************************************~**~***************
* Did this so the parent had a consistent method to call
* between value panels.
*******************************************************l
public void deselectAII0
clearAII0;
}




I*******************************************************
* wipes out the SLE. 13 5

CA 0220926~ l997-06-27 --~


*t***********************************$*********~********/
public void clearA110 {
Value I .setText("");
}




I*******************************************************
* If the mouse leaves the SLE, notify anyone who's listening
**~****************************************************1
public boolean handleEvent(Event evt) {
if(evt.id -- Event.MOUSE_EXIT && evt.target instanceof TextField) {
this.postEvent(new Event(this,10001,"ue_selecte~itPrn"));
}




return super.handleEvent(evt);
}




I*******************************************************
* Reshapes and re-lays out the cont~inf~r
*******************************************************l
public void reshape(int x, int y, int w, int h) {
super.reshape(x, y, w, h);
getLayoutO.layoutContainer(this);
}
}




136

CA 0220926~ 1997-06-27


package tcg.homeconnection;
import java.awt.*;
import java.util.*;

I*******************************************************
* Class: ValueRange
* Written by: Brian Duncan
* Date:
* Purpose: This class extends ValuePanel (Panel) to provide
* a range, comprising of two textFields.
*******************************************************/
public class ValueRange extends ValuePanel {
TextField LowLabel, ~TiphT abel;
RangeText Valuel, Value2;
int whichFocus = I;

I*******************************************************
* Constructor: Parameter is Category Name
*******************************************************l
public ValueRange(String argS) {
name = argS;
setLayout(null);
Valuel = new RangeText(5, this, 1);
Valuel cetRackground(Color.white);
Value2 = new RangeText(5, this, 2);
V~hl~.cPtR~rL ground(Color.white);
LowLabel = new TextField("Min:",4);
LowLabel cetRarkEround(color.lightGray);
LowLabel cetF~lit~hle(false);
HighLabel = new TextField("Max:",4);
HighLabel cetRarkground(color.lightGray);
HighLabel cetF~lit~ble(false);
setRIrkground(Color.lightGray);
add("LowText", LowLabel);
add("LowRange", Value I );
add("HighText", HighLabel);
add("HighRange", Value2);
}




I*******************************************************
* Override reshape, to force sizes of the labels and
* textfields.
*******************************************************l
public void reshape(int x, int y, int w, int h) {
super.reshape(x,y,w,h);
LowLabel.reshape(w/2 - 55,h/2 - 25, 40, 20); 13 7

. CA 0220926~ 1997-06-27


HighLabel.reshape(w/2 - 55, h/2+5,40,20);
Value I .reshape(w/2- 1 0,h/2 - 25, 60, 20);
Value2.reshape(w/2- 1 0,h/2+5 ,60,20);
}




I*******************************************************
* Override paint to draw a box around the panel.
*******************************************************l
public void paint(Graphics g) {
super.paint(g);
g .setColor(Color.black);
g.drawRect(0,0,thic ci7~0 width-l, this.size().height-l);
}




I*******************************************************
* Returns the low and high values of the range in a Vector.
* If the low value is empty, it sets the value to the high value.
* If the high value is empty, it sets the value to the low value.
* If the low value is higher than the high value, it returns 'None'.
*******************************************************l
public Vector getValuesO {
Vector Values = new Vector(l);
String Vall, Val2;
Val I = Value I .getTextO.trimO;
Val2 = Value2.getTextO.trimO;

Vall = (Vall.lengthO > 0) ? Vall: "O";
Val2 = (Val2.1engthO > 0) ? Val2: "0";
if (Vall.equals("O") && Val2.equals("0")) {
Valuçs ~ lFlpment(~None~
} else {
if(Val I .lengthO < V~l~ lengthO) {
String Spaces= " ";
Vall = Sp~ces cubstring(o~ Val2.1engthO - Vall.length())+Vall;
}




if(Val I .compareTo(Val2) <= O) {
Valll~s ~rlrlFlement(vall+"-"+val2);
} else {
Valu~s.~clrlF.lement("None");
}
return Values;

}




/*******************************************************
* Did this so that the calling method has the same call
* for all value panels.
*******************************************************l
public void deselectAllO { 13 8

CA 0220926~ 1997-06-27 ,f

clearAI10;
}




I*******************************************************
* Clears out the textFields.
*******************************************************/
public void clearA110 {
Value I .setText("");
Value2 .setText("");
}




I*******************************************************
* Don't allow any keystrokes except A-Z, a-Z, Tab,
* Rarl~r~re, delete, and 1-0
*******************************************************l
public boolean keyDown(Event evt, int key) {
if((key > 31 && key < 48) 11 (key > 57 && key < 92) 11 (key > 92 && key < 127)) {
return true;
} else
return false;
}




I*******************************************************
* Check for tab, if so, switch to the next textfield.
*******************************************************l
public boolean keyUp(Event evt, int key) {
if((char) key == '\t') {
switchFocus();
this.postEvent(new Event(this,10001,"ue_selecte~item"));
}




return false;
}




I*******************************************************
* If the mouse moves out of the textfields, notify anyone
* who cares.
*******************************************************l
public boolean handleEven~(Event evt) {
if(evt.id = Event.MOUSE_EXlT && evt.target instanceof TextField) {
this.postEvent(new Event(this, 10001 ,"ue_selecte~lits~m ~
}




return super.handleEvent(evt);
}




I*******************************************************
* If Toggle focus between the textfields. This allows
* Tabbing functionality.
*******************************************************l
public void switchFocus() {
if (whichFocus = I) {
Value2.requestFocusO;
whichFocus = 2;
} else {
Value I .requestFocusO; 13 9

.. CA 0220926~ l997-06-27 -
:.

whichFocus= I;
}
}




/*******************************************************
* Class: RangeText
* Written by: Brian Duncan
* Date:
* Purpose: This class extends TextField, and was written
* to have a textfield that has a tag value.
*******************************************************l
class RangeText extends TextField {
ValueRange cParent;
int ID;

I*******************************************************
* Constructor: Length, Parent, Tag #
*******************************************************l
public RangeText(int length, ValueRange par, int argI) {
super(length);
cParent = par;
ID = argI;
}
}




140

CA 0220926~ l997-06-27 r_

package tcg.homeconnection;
import java.awt.*;
import java.util.*;

/****************************************************
* Interface: ValuePanel
* Written by: Brian Duncan
* Date:
* Purpose: This interface provides method declarations for the
* value panels: ValueSingle, ValueRange, and ValueDynamicList.
****************************************************l
public abstract class ValuePanel extends Panel{
protected String name;
//abstract method can handle these.
public String getNameO {
retum name;
};
/IJust stubbed these methods, some panels need 'em, some don't.
public void a~ Tt~mc(Vector ArgV) { }
public int getMaxWidthO { retum O; }
public void setNeedsRefresh(boolean argB){}
public boolean getNeedsRefreshO { retum false; }
//AII value panels need these, SeekFind relies on 'em.
public abstract void clearAI10;
public abstract Vector getValuesO;
public abstract void deselectAI10;
}




141

. CA 0220926~ 1997-06-27

package tcg.homeconnection;
import java.util.*;
import java.awt.*;

/*******************************************************
* Class: ValueDyn~micT ict
* Written by: Brian Duncan
* Date:
* Purpose: This class extends ValuePanel (Panel) to provide
* A List with ~ ition~l filnction~lity, in- In~ling p~ uisile
* Proc~c~in~.
*******************************************************l
public class ValueDynarnicList extends ValuePanel {
//The listbox
List Listl;
//Label to indicate to the user that there is a p.~ ui~
//Category.
Label preLabell, preLabel2;
//The Category Name of the pl ~,.e.~uiai~e (if any)
String ~ ui ~
//Need this to toggle between the F~ ui~ panel and the
//List panel
CardLayout layout;
//~nrlic~t-lr that tells the calling method that this panel'
//needs refreshing (IJpdating the list).
boolean needsRefresh = false;
//lndicates whether or not the message is being shown.
boolean messageShown = false;

/*******************************************************
* Constructor.
* argS: Category name of this panel's parent.
* argS2: l~.e~lui~ CategoryName
*******************************************************/
public ValueDynamicList(String argS, String argS2) {
Panel messagePanel = new PanelO;
messagepal~cl.setLayout(new GridLayout(4, 1 ));
name = argS;
pl~ Uisil~ = argS2;
layout = new CardLayout(l, I);
setLayout(layout);
Listl = new List(lO, true);
setRacL-ground(Color.lightGray);
add("List", Listl);
//If there's a prerequisite, add prerequisite message.
142

CA 0220926~ 1997-06-27 -- .
' '..

if(prerequisite.lengthO > ~) {
preLabell = new Label("You must choose a ",Label.CENTER);
preLabel I .setFont(new Font("TimesRoman",Font.BOLD, 14));
preLabel2 = new Label(prerequisite+" first.",Label.CENTER);
prPT ~bel'~ cPtFont(new Font("TimesRoman",Font.BOLD,14));
I/Add a blank label to top and bottom, to center the
l/two me~nineful ones.
messagePanel.add(new Label(""));
messageP~nPI a~l~l(preLabel I );
messageP~nPI ~I(preLabel2);
messageP~nPI ~d~1(new Label(""));
add("Message",messagePanel);
/lIf prerequisite, the prerequisite must be shown
//initially, until the pie.~.luisiL~ caetgory is
//chosen.
Iayout.show(this, "Message");
messageShown = true;
}
}




/*$*****************************************************
* Constructor. Use to default Prerequisite to "".
* argS: Category name of this panel's parent.
*******************************************************/
public ValueDynamicList(String Name) {
this(Narne, "");

}




/*******************************************************
* Adds a vector of items to the list.
*******************************************************l
public void ~Al1Tt~prnc(vector ArgV) {
for(Enumeration e = ArgV.elementsO;e.hasMoreElements0;)
Listl ad~lTtPm((String)e.nextElement0);
//If this is a child category, show the list, now that
//the prerequisite category has been chosen.
if(prerequisite.lengthO > ~) {
layout.show(this, "List");
messageShown = false;
}




I*******************************************************
* Return a vector of the selected items, or "None" as the
* only element if none are selected.
*******************************************************l
public Vector getValuesO {
String[] Items;
Vector Values; 14 3

~ CA 0220926~ l997-06-27 .


Items = Listl.getSelectedItemsO;
Values = new Vector(Items.length);
fo~int iLoop=O; iLoop < Tt~mclPn~th, iLoop++)
V~l-.es ~d~Fl~ment(ItemstiLoop]);
if( V~lu~s Ci7f'0 = O) {
V~h-~s ~ Fl~ment(~None~
}




return Values;
}
/*******************************************************
* Sets the needsRefresh flag.
*******************************************************/
public void setNeedsRefresh(boolean argB) {
needsRefresh = argB;
/Mo ahead and switch to the list, because we know that
//It will be populated as soon as the user sees this
/tanyway.
if(needsRefresh) {
layout.show(this, "List");
messageShown = false;
}
}




I*******************************************************
* Returns the needsRefresh flag
*******************************************************l
public boolean getNeedsRefreshO {
return needsRefresh;
}




/*******************************************************
* Clears all items from the list. If this is a child
* category, show the p~ ui~iLe message.
*******************************************************t
public void clearAI10 {
Listl ~e!Tt~mc(O,Listl.cou,lLI~ sO-l);
if(prerequisite.lengthO ~ ~) {
layout.show(this,"Messagen);
messageShown = true;
}




setNeedsRefresh(false);
}




/*******************************************************
* Deselects all selected items from the list.
*******************************************************l
144

CA 0220926~ 1997-06-27
:

public void deselectAll0 {
int iLoop;
for(iLoop = 0; iLoop < Listl countTtf~mc(); iLoop++) {
Listl .deselect(iLoop);
}
}




/*******************************************************
* Returns the String width of the widest item in
* the list.
*******************************************************/
public int getMaxWidthO {
int temp, maxWidth = 0;
FontMetrics fm = getFontMetrics(this.getFontO);
for(int iLoop=0;iLoop<Listl .con~llT~ O;iLoop++) {
temp = fm.stringWidth(Listl.getItem(iLoop));
if( temp > maxWidth) maxWidth = temp;
}




return maxWidth;

}
I*******************************************************
* Implemented to notify anybody watching that an Item was
* selected.
*******************************************************l
public boolean handleEvent(Event evt) {
if (evt.id = Event.LIST_SELECT 11 evt.id -- Event.LIST_DESELECT) {
1/ ((Component)getParentO).handleEvent(new Event(this,lOOOl,"ue_selecterlitçm"));
this.postEvent(new Event(this,l0001,"ue_selectç~1it~r "));
}




return super.handleEvent(evt);
}




I*******************************************************
* Reshapes and re-lays out the container
*******************************************************/
public void reshape(int x, int y, int w, int h) {
super.reshape(x, y, w, h);
getLayoutO.layoutContainer(this);
}
I*******************************************************
* Override paint to draw a box around the panel.
*******************************************************/
public void paint(Graphics g) {
super.paint(g);
//Only draw the box if the prerequisite message is
//being shown.
if(messageShown) { 14 5

CA 02209265 l997-06-27 --

g.setColor(Color.black);
g.drawRect(O,O,thic ci7~0 width 1, this.sizeO.height-l);
}
}




146

. CA 0220926~ l997-06-27 .-

package tcg.homeconnection;

importtcg.homeconnecti-n *;
import java.awt.*;
import java.util.*;

/**********************************************************
* Class: CategoryPanel
* Written by: Brian Duncan
* Date:
* Purpose: A list eytrncion that displays a list of
* category headers, keeping track of their ~csoci~tçd
* category objects.
* along with an array of m~tr~lin~ lrd category
* objects.
**********************************************************l
public class CategoryPanel extends Panel {
public List listl;
Vector Ca~goliei,


/**********************************************************
* CollaLI u~,lul for the CategoryPanel.
*
* Accepts one integer parameter that specifies how many
* list items should be displayed on the screen at the s arne
* time.
**********************************************************l
public CategoryPanel(int ArgI) ~

setLayout(new BorderLayoutO);
listl = new List(10, false);
listl cetR~r~ground(Color.white);
add("Center",listl);
Categories = new Vector(ArgI);
}




I**************************************************
* Adds a category to the list. Creates a new category object
**************************************************l
public void addCategory(String ArgS1, String ArgS2, String ArgS3, String ArgS4, String ArgS5) {
listl .addItem(ArgS2);
Categories ~ Fl~rnent(new Category( ArgS1, ArgS2, ArgS3, ArgS4, ArgS5 ));

}




I**************************************************
147

CA 0220926~ 1997-06-27

* Returns the ~ccoci~tpd value panel of the category
* name passed in.
**************************************************l
public ValuePanel getValuePanel(String ArgS) {
Category whichOne;
ValuePanel pPanel=null;
whichOne = getCategory(ArgS);
if(whichOne != null)
pPanel = whichOne.getPanelO;
return pPanel;
}




I**************************************************
* Returns a category object that collei~,onds to the item #
* passed in.
**************************************************l
public Category getCategory(int ArgI) {
return (Category) Categories.elementAt(ArgI);
}




I********************************************************
* Returns a category object that corresponds to the category
* name passed in.
********************************************************l
public Category getCategory(String ArgS) {
Category whichOne = null;
for(int iLoop=0; iLoop < Categories.sizeO; iLoop++) {
whichOne = (Category) Categories.elementAt(iLoop);
if(whichOne.getNarneO .equals(ArgS))
break;
}




return whichOne;
}




/**
* Returns an array of all category objects in the list.
*/

public Vector getAllCategoriesO {
return Categories;
}




/**
* Sets the app. o~l ;at~ category List item based on index.
148

,_ CA 0220926~ 1997-06-27 ._

public void selectCategory(int argI) {

list l .select(argI);
}




/**
* Sets the dpl)lOIJlia~e category List item based on name.
*l
public void selectCategory(String ArgS) {
String header;
Category whichOne;
for(int iLoop=0;iLoop < C~,go, ics.size(); iLoop++) {
if(getCategory(iLoop).getNameO.equals(ArgS))
listl .select(iLoop);
}




/**
* Unselects all selected items in all categories.
*l
public void deselectAI10 {
for( Enumeration e = Categories.elementsO; e.hasMoreElementsO; )
((Category) e nçYtFl~ment0) deselectAll0;
}




public int countCategoriesO {
return listl.conntTt~-mc0;
}




public int getMaxCatWidth0 {
int temp, maxWidth = 0;
FontMetrics frn = getFontMetrics(this.getFontO);
for( Enumeration e = Categories.elementsO; e.hasMoreFlementc0;) {
temp = fm.stringWidth(((Category) e n~ytFlemPnt()).getHeader0);
if( temp > maxWidth) maxWidth = temp;
return maxWidth;
}




public int getMaxValueWidth0 {
int temp, maxWidth = 0;
for( Enumeration e = Categories.elementsO; e.hasMoreElementsO;) {
temp = ((Category) e.nextElementO).getPanel0.getMaxWidth0;
if( temp > maxWidth) maxWidth = temp;
return maxWidth;
}




/**************************************************
* Returns a Vector of all categories that have a 14 9

CA 0220926~ l997-06-27
. , .

* prerequisite category of the one passed in
**************************************************l
public Vector getPrerequicites(String argS) {
Vector parents = new VectorO;
Category whichOne;
for(Enumeration e=Categories.elements(); e.hasMoreElementsO; ) {
whichOne = (Category) e.nextElement();
if(whichOne.getPrerequisiteO .equals(argS))
parentC ~d~ Pment(whichOne);
}




return parents;
}




public void reshape(int x, int y, int w, int h) {
super.reshape(x, y, w, h);
getLayout().layoutContainer(this);
}




/************************************************
* Removes all CaL~gOI ies from the CatPanel object.
************************************************/
public void removeAllCategoriesO {
Categories.removeAllElementsO;
listl .clearO;
}
}




150

CA 0220926~ 1997-06-27 _

package tcg.homeconnection;
import tcg.homeconnection.*;
import java.awt.*;
import java.util.Vector;

I***********************************************************
* Class: Category
* Written by: Brian Duncan
* Date:
* Purpose: This class represents a dynamic category object.
* A category is a search criterion that the user can use
* to formulate a query.
* This object contains a value panel that's one of four types:
* Single, Range, DynamicList, StaticList
***********************************************************l
public class Category {
//The value panel that's associated with this category
ValuePanel pValuePanel;
//The category Name - Not to be confused with the Header
String Name;
//Type of category - Single, Range, DynamicList, StaticList
String sType;
//Max length of the category entry field(s).
int iLength;
//Header of this category - Shows up on the Category Panel.
String sHeader;
//The prerequisite Category name, if any, for this category.
String prerequisite;

I***************************************************
* Constructor for the Category Class
* The first parameter of this Constructor specifies the Category Name,
* 2nd is Header, 3rd is Length, 4th is type, 5th is pre-requisite category.
***************************************************l
public Category(String ArgSI, String ArgS2, String ArgS3, String ArgS4, String ArgS5) {
Name = ArgS 1;
sHeader= ArgS2;
iLength = Integer.valueOf(ArgS3).intValueO;
sType = ArgS4;
prerequisite = ArgS5;
//Create the valuePanel object for this category, based
//on category type.
if (sType.equals("Single"))
pValuePanel = new ValueSingle(Name); 151

CA 0220926~ 1997-06-27

else if( sType.equals("Range"))
pValuePanel = new ValueRange(Name);
else if( sType.equ~lc("Dyn~miçT ict'l) 1I sTyFe eql~lc("StaticList"))
pValuePanel = new ValueDynamicList(Name, prerequisite);
else
pValuePanel = new ValueSingle(Name);
}




I*************************************************
* Returns the maximum allowed length
*************************************************l
public int getT ~ngthO {
return iLength;
}




I*************************************************
* Returns the category type
**~**~***********************
public String getTypeO {
return sType;

}




I*************************************************
* Returns the valuePanel object associated with this
* category
*************************************************l
public ValuePanel getPanelO {
retum pValuePanel;
}




I*************************************************
* Returns the name of this category
*************************************************l
public String getNameO {
return Name;
}




I*************************************************
* Returns the display header for this category
*************************************************l
public String getHeaderO {
return sHeader;
}




I*************************************************
* Returns the values in the ValuePanel associated with this
* category. It does this by calling the getValues() method
* of the valuePanel 15 2

--. CA 0220926~ 1997-06-27


* ~see tcg.homeconnPction ValueSingle#getValues
* ( ~see tcg.homeconnection.ValueRange#getValues
* (~,see tcg.homeconnection.ValueDynamicList#getValues
* (~see tcg.homeconnection.V~ eSt~ticList#getValues
*************************************************l
public Vector getValuesO {
return pValuePanel.getValues();
}




/*******************************************************
* Adds selection items to the a~"ol,lial~ valuepanel.
*******************************************************l
public void ~dfl~t~rnc(Vector ArgV) {
pValuePanel ~d~l~t~rnc(Argv);
}




I*******************************************************
* Clears all selection items from the a~plopfiate v~l-lep~-lPI
*******************************************************l
public void clearAIIO {
pValuePanel.clearAIIO;
}
I*******************************************************
* Deselects all selection items from the appropriate valuepanel.
*******************************************************l
public void deselectAIIO {
pValuePanel dPce!~ctAIIO;
}




I********************************************************
* Sets the 'needsRefresh' flag.
* Does this by calling the appropriate valuepanel's setNeedsRefreshO
* method.
********************************************************/
public void setNeedsRefresh(boolean argB) {
pValuePanel.setNeedsRefresh(argB);
}




I****************************************************
* Gets the 'needsRefresh' flag.
* Does this by calling the appropriate valuepanel's getNeedsRefreshO
* method.
****************************************************l
public boolean getNeedsRefreshO {
return pValuePanel.getNeedsRefresh();
}




I****************************************************
* Get's Prerequisite category narne, if any.
**************$*************************************/
public String getPrerequisiteO { 153

-~ CA 02209265 l997-06-27 --

} return prerequisite;




154

-- CA 0220926~ 1997-06-27 ,~

package tcg.tools;
import java.io.*;
import java.util.*;
public class Manipulation {
/** This class works similar to Perl's 'join'. It takes a
* separator string, and a vector, and joins them all
* together, separating them with the separator. It
* Retums them all as a string.
*l
public static String join(String ArgS, Vector ArgV) {
Enumeration e = ArgV.elementsO;
String joined = "";
if(!ArgV.isEmptyO) {
joined = (String) e nPYtFlPrnent0;
while~ e.hasMoreElementsO )
joined += ArgS + (String) e.nextElement();
return joined;
}




/* * This class is just a front end for the above join method.
* It takes a character instead of a string as a separator.
*/
public static String join(char ArgC, Vector ArgV) {
return join( String.valueOf(ArgC), ArgV);

}




/** Front-end function for the Split method. This one takes character and converts it to string.
*/
public static Vector split(char ArgC, String ArgS) {
return split(String.valueOf(ArgC), ArgS);
}




/** This method imitates the perl 'Split' function . It splits
* apart a string into a vector of strings based on a
* particular separating character.
*l
public static Vector split(String ArgS I, String ArgS2) {
Vector items;
int nextPos;
items = new VectorO;
while(ArgS2.1engthO > ~) {
nextPos = ArgS2.indexOf(ArgS l);
if(nextPos < 0) {
itPrnc ~rl(lF.lPrnent(ArgS2); 155

-- CA 0220926~ 1997-06-27

ArgS2 = "";
} else {
itPmC ~ArlF,lement(Arg~ cubstring(O,nextPos));
ArgS2 = Arg~ cnbstring(nextpos+Args I .length());
}
}




return items;
}




/*****************************************************
* This gets the value of a particular tag in the passed in
* .ini file, and returns it.
* This version doesn't worry about group na~nes.
*****************************************************l
public static String getINIString(String filPn~rne, String tag) {
File f;
FileInputStream ffn;
D~t~Tnrut.~tream dln;
String line;
f= new File(filename);
try {
fln = new FileInputStream(f);
dln = new DataInputStream(fIn);
//Look for tag in file. Don't come back until you get it or
//EOF.
do {
line = dIn.readLine();
} while((line != null) && line.indexOf(tag) == -1);
if(line != null)
line = line.substring(line.indexOf('=')+ I ).trimO;
if(line=null)
Iine= "none";
return line;
} catch(lOException e) {
System.out.println("Unable to open INI File!\n");
return null;

}
I*****************************************************
* This gets the value of a particular tag in the passed in
* .ini file, and returns it.
* This version does it based on group name.
*****************************************************l
public static String getINlString(String filename, String group, String tag) {
File f; 15 6

- CA 0220926~ 1997-06-27 i-

FileInputStream fln;
DatalnputStream dln;
String currGroup = "";
String line;
String returnValue = null;
f= new File(filename);
try {
fln = new FilelnputStream(f);
dln = new DatalnputStream(fln);
//Look for tag in file. Don't come back until you get it or
//EOF.
while((line = dIn.readLineO) != null) {
if(line.startsWith("[") && line.endsWith("]")) {
//This is a group header.
if(!currGroup.equals(group)) {
currGroup = line.substring( I ,line.lengthO- 1 );
continue;
} else
//The group header we needed is over, stop.
break;
}




if(line.indexOf(tag) != -I && currGroup.equals(group)) {
returnValue = line.substring(line. indexOf('=')+ I ) .trimO;
break;




if(returnValue=null)
returnValue= "none";
return returnValue;
catch(lOException e) {
System.out.println("Unable to open INI File!\n");
return null;
}
}




/** This method pads the passed-in s~ing with spaces until
* it is the specified length, then returns the modified string.
*l
public static String padSpaces(String ArgS, int Argl) {
String Spaces = " ";
if(ArgS.lengthO > Argl)
return ArgS;
else
return ArgS + Spac~os cubstring(o~ Argl-ArgS.leng~);
}

-- CA 0220926~ l997-06-27 --


/** This method pads the passed-in string with zeros until
* it is the specified length, then returns the modified string.
*/
public static String padZeros(String ArgS, int Argl) {
return "000000000000000".substring(0,ArgI-ArgS.length())+ArgS;
}




/** This method counts the occurrences of a substring inside
* a string, then returns the count.
*l
public static int countOccurrences(String ArgS, String ArgS2) {
int next = 0;
int count = 0;
while (next != -1) {
next= ArgS.indexOf(ArgS2, next+l);
if (next != - I )
count++;
return count;
}




158

- CA 0220926~ 1997-06-27 ,~
~pe~lx B
import java.io.*;
import java.net.*;
import java.awt.*;
import java.util.*;
import tcg.tools.*;
import jet.connect.*;
public class SFServer extends Thread {
public final static int DEFAULT_PORT = 7777;
protected int port;
protected ServerSocket listen socket;
protected StartCol startCol;
public File f;
public RandomAccessFile lOut;
public Vector xrefCategory;
public Hashtable xrefColumn, xrefType, xrefLength;
public Hashtable xrefHeader, xrefColType, xrefPrerequisite;
public DbEnv dbenv = null;
public DbDbc dbcon = null;
public Hashtable iniParms;
public ThreadHandler handler;
public Frame frame;
public Label users, threads;
//Exit with an error message, when an exception occurs.
public static void fail(Exception e, String msg) {
System.out.println(msg+":"+e);
System.exit(1);
}




//Create a ServerSocket to listen for connections on; start the thread.public SFServer(int port, boolean isHub) {
//Create out server thread with a name.
super("Server");
if(port = 0) port = DEFAULT_PORT;
this.port = port;
f= new File("Usage.log");
try {
lOut = new RandomAccessFile(f, "rw");
lOut.seek(lOut.length0);
} catch(lOException e) {
System.out.println("Unable to open Usage file.\n");
}




//Populate the category information
populateXRefO;
//Populate the database access variables;
populateDBlnfoO;
//Create and open an ODBC Connection
while(true) {
try { 1 5 9

- CA 0220926~ 1997-06-27 ---

dbenv = DbEnv.SQLAllocEnvO;
break;
} catch(DbSqlException e) {
}
}




//Call the odbc driver and populate the column data type hashtable
if (!isHub)
getColTypesO;
try {
listen socket = new ServerSocket(port);
} catch (IOException e) {
fail(e, "Exception creating server socket");
/I Create a thread group for our conn~ctionc
System.out.println( Server: liseing on port " + String.valueOf(port));
//Create a window to display our connections in
frame = new Frame("Seek&Find: "+String.valueOf(port));
f~rn~ setT ~yout(new GridLayout(2,2));
fiame.resize(200, l00);
users = new Label("");
threads = new Label(nn);
fr~me ~d-l("Label l",new Label("Connections:"));
frame.add("Users",users);
fr~me ~d~i("Label 2",new Label("Threads:"));
frame.add("Threads",threads);
handler = new ThreadHandler(this);
// f.add(handler);
// frame.showO;
// Create a thread to kickoffthe COL request at the
// d~)plU~lidLe time.
if(!isHub && !(getINI("HUBURL").equals("none")) && !getINI("COLLECTTIME").equals("0"))
startCol = new StartCol(this);
// Start the server listening for connections.
this.startO;
}




public void setStat(int iUsers, int i~hreads) {
users.setText(String.valueOf(iUsers));
threads.setText(String.valueOf(iThreads));
//The body of the server thread. Loop forever, listening for and
//accepting conenctions from clients. For each connection,
//create a Connection object to handle com~n--nic~tion through the
//new Socket. When we create a new connection, add it to the
//Vector of connections, and display it in the List. Note that we
//use synchronized to lock the Vector of connections. The Vulture
160

CA 0220926~ 1997-06-27 _

//class does the same, so the vulture won't be removing dead
//connections while we're adding fresh ones.
public void run() {
try {
while(true) {
Socket clientSocket = listen_socket.acceptO;
while(!handler.startClient(clientSocket)) {
System.out.print("fail! ");
}
catch (IOException e) {
fail(e, "Exception while listening for connections");
}
}




/** This method populates the XREF vectors from the
* XREF.DAT file.
*/
public void populateXRefO {
File f;
FileInputStream fIn;
DataInputStream dIn;
String line, category, column, type, length, header, prerequisite;
int Index, ColIndex, TypIndex, T . nTn~lex, HeadIndex;
f= new File("xref.dat");
line= "First";
try {
fIn = new FileInputStream(f);
dIn = new DataInputStream(fIn);
xrefCategory = new Vector();
xrefColumn = new HashtableO;
xrefType = new HashtableO;
xrefHeader = new HashtableO;
xrefLength = new HashtableO;
xrefColType = new HashtableO;
xrefPrerequisite = new Hashtable();
while(line != null) {
line = dIn.readLineO;
if(line != null) {
Index = line.indexOf('=');
if(Index > O) {
category= line.substring(O,Index).trim();
line = line.substring(lndex+l) trimO;
//Column, Type, Length, Header
ColIndex = line.indexOf('l');
TypIndex = line.indexOf('l', ColIndex+l); 161

f CA 0220926~ 1997-06-27 r-

T PnTndl?x = line indexOf('l', Typlndex+l);
Headlndex = line.indexOf('l', I .onTn~i~oy+l);
column = line.substring(0, ColIndex).trimO;
type= line.substring(Collndex+l, Typlndex).trimO;
length = line.substring(Typlndex+l, LenIndex).trimO;
if(H~Tn~x > 0) {
header= line.substring(l ~nTnd~x+l~ He~Tn~Y).trim0;
prerequisite= line.substring(He~lTn~lex+l).trim0;
} else {
header= line cubstring(T.Pnln~lPY+I) trimO;
prerequisite= "";
}




xrefCategory ~ F.l~ment(category);
xrefColumn.put(category, column);
xrefType.put(category, type);
xrefLength.put(category, length);
xrefHeader.put(category, header);
xrefPrerequisite.put(category, pl~ uisil~);

}
} catch(IOException e) {
System.out.println("Unable to open XReference File!\n");
}




/** This method determines the data type of each column in the
* XREF.DAT file.
~1
public void getColTypesO {
int iCount;
String genType;
DbColDesc colDesc;
DbDbc dbcon = null;
DbStmt dbstmt = null;
DbVarChar data[] = new DbVarChar[20];
Vector columns;
String sqlString;
Enumeration eCat;
eCat = xrefCategory.elementsO;
columns = new Vector();
while( eCat.hasMoreElementsO )
colllnnnc ~ Flement(xrefcolumn~get((string)ecat~nextElemento));
sqlString = "SELECT DISTINCT "+getINI("lDCOLUMN")+",";
sqlString += Manipulationjoin(",",columns); 162

CA 0220926~ 1997-06-27 -'

sqlString += " FROM "+getINl("DBTABLE");
//Connect to ODBC Driver

while(true) {
try {
dbcon = dbenv.SQLAllocConnect0;
dbcon.SQLConnect(getINI("DATASOURCE"),getINI("USERID"),getINI("PASSWORD"));
dbstmt = dbcon.SQLAllocStmtO;
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
break;
} catch(DbSqlException e) {
}
}




//Bind the data into arrays, column by column.

iCount = 2;
for( eCat = xrefCategory.elem~ntc0;eCat.hasMoreElements0;) {
colDesc = dbstmt.SQLDescribeCol(iCount);
genType = getGeneralType(colDesc.getSqlTypeO);
xrefColType.put(eCat.nextElementO,genType);
iCount++;
}




colDesc = dbstmt.SQLDescribeCol(l);
genType = getGeneralType(colDesc.getSqlTypeO);
iniParms.put("IDTYPE",genType);

dbstmt.SQLFreeStmt(Db.SQL_DROP);
dbcon.SQLDisconnect();
dbcon.SQLFreeConnectO;
}




public String getGeneralType(int Type) {
String returnValue;
if(Type=Db.SQL_BlGINT 1I Type=Db.SQL_DECIMAL 1I Type=Db.SQL_FLOAT
Type==Db.SQL_INTEGER 1I Type=Db.SQL_NUMERIC 1I Type=Db.SQL_REAL
Type=Db.SQ~_SMALLINT 1I Type=Db.SQL_TINYINT)
returnValue = "INT";
else if (Type---Db.SQL_CHAR li Type=Db.SQL_LONGVARCHAR 11
Type=Db.SQL_TlME 1I Type=Db.SQL_TIMESTAMP 1I Type=Db.SQL_VARCHAR)
returnValue = "CHAR";
else if (Type==Db.SQL_DATE)
returnValue= "DATE"; 163

CA 02209265 1997-06-27

else
returnValue = "OTHER";
return returnValue;
/lStart the server up, listening on an optionally specified port
public static void main(StringO args) {
int port = 0;
boolean isHub = false;
if (argC l~n~h >= l) {
try {
port = Integer.parseInt(args[0]);
} catch (NurnberForrnatException e) { port= 0;
}
}




if (arg~ l~ngth = 2)
isHub = true;
new SFServer~port, isHub);
}




public String getINI(String ArgS) {
return (String) iniParrns.get(ArgS);
}




public void populateDBInfio0 {
String tempString;
iniParms = new HasbtableO;

iniParms.put("DATASOURCE", Manipulation.getINIString("HCINI.INI","DATASOURCE"));iniParms.put("DBTABLE", Manipulation.getINIString("HCINI.INI","DBTABLE"));
iniParrns.put("IDCOLUMN~ nirul~tiomgetINIstring(llHcINI~INpl~l~IDcoLuMN~
iniParms.put("USERID", M~nirul~tion.getINIString("HCINI.INI","USERID"));
iniParrns.put("PASSWORD", Manipulation.getINIString("HCrNI.INI","PASSWORD"));
iniP~nnc put("HUBURLn, Manipul~tion getINIString("HCINI.INI","HUBURL"));
iniParms.put("PRODUCTTYPE", Manipulation.getINIString("HCINI.rNI","PRODUCTTYPE"));
iniParms.put("HTMLTEMPLATE", Manipulation.getINIString("HCINI.INI","HTMLTEMPLATE"));
iniParms.put("HTMLREFRESH", Manipulation.getINIString("HCINI.INI","HTMLREFRESH"));
iniParrns.put("DEBUG", Manipulation.getlNIString("HCINI.INI","DEBUG"));
tempString = Manipulation.getrNIString("HCINI.INI","HTMLDIRECTORY");
Mlf htmlDirectory doesn't have ~r at end, add it.

if(!tempString.equals("nonen~)
if(!tempString.endsWith("r'))
tempString+="/";
iniParms .put("HTMLDIRECTORY",tempString);
iniParms.put("COLLECTTIME", Manipulation.getlNIString("HCINI.INI","COLLECTTIME"));
iniParms.put("SERVERADDRESS",Manipulation.getINlString("HCINI.INI","SERVERADDRESS"));
164

CA 0220926~ 1997-06-27 ,-'




/IThis class is a timer thread, that kicks of at the appropriate
/Itime and makes a COL request once a day.
class StartCol extends l~read {
protected SFServer cParent;
protected StartCol(SFServer ArgC) {
super("COL Kickof~');
cParent = ArgC;
this.startO;
}




public void runO {
Date currDate, kickDate;
String time = cParent.getlNl("COLLECTTlME");
long kickoff;
int index;
boolean first = true;
String inLine;
if(time.equals("none"))
time = "00:00";
currDate = new DateO;
kickDate = new DateO;
index = time.indexOf(":");
kici;Date.setHours(lnteger.valueOf(time.substring(O,index)).intValueO);
kickDate.setMinutes(lnteger.valueOf(time.substring(index+l)).intValueO);
while (true) {
try {
sleep(30000);
currDate = new DateO;
if( currDate.getHoursO--kickDate.getHoursO && currDate.getMinutes() >=
kickDate.getMinutesO ) {
if(first) {
System.out.println("Started Profile Collection at~+Strin~.valueOf(currDate.getHoursO)+": "+String.valueOf(currDate.getMinutes()));
processCOLRequestO;
first = false;
}




} else if ( currDate.getHoursO > kickDate.getHours() ) {
if(first) {
inLine = processCOLRequest();
System.out.println("Profile Collection at
"+Manipulation.padZeros(String.valueOf(currDate.getHours()),2)+":"+Manipulation.padZ:eros(String.valu
eOf(currDate.getMinutesO),2)+" - "+inLine);
first = false; 16 5

- CA 0220926~ 1997-06-27 f~-


} else {
first= true;
} catch(Interrupte~FYreFtion e) {};
}




/I Process the DATA Collection request (COL)
public String processCOLRequestO {
DbStmt dbstmt = null;
DbDbc dbcon = null;
DbVarChar data[l = new DbVarChar[20];
String localHost;
String address;
Enumeration eCat;
String category, type, prerequisite, sqlString, tempSQL, currCat, outLine, inLine;
Vector where, currVals, allCatVal;
String routingTag;
int iLoop;
inLine = "";
eCat = cParent.xrefCategory.elementsO;
where = new VectorO;
while( eCat.hasMoreElementsO ) {
category = (String) eCat.nextElement();
type = (String) cParent.xrefType.get(category);
prerequisite = (String)(cParent.xrefColumn.get((String) cParent.xrefPrerequisite.get(category)));
if(prerequisite--I~ull)
prerequisite = """;
if(type.equals("DynamicList") 1I type.equals("StaticList")) {
tempSQL = "SELECT DISTINCT "'+category+"', ";
tempSQL += cParent.xrefColumn.get(category);
tempSQL += ", "+prerequisite+" FROM ";
tempSQL += cParent.getINI("DBTABLE")+" WHERE ";
tempSQL += cParent.xrefColumn.get(category)+" IS NOT NULL";
if (cParent.xrefColType.get(category).equals("CHAR"))
tempSQL += " and "+cParent.xrefColumn.get(category)+" O "";
where.addElement(tempSQL);
}
}




sqlString = Manipulationjoin(" UNION ",where);
try {
/lConnect to ODBC Driver 16 6

CA 0220926~ 1997-06-27 ,~'


dbcon = cParent.dbenv.SQLAllocConnect();

dbcon.SQLConnect(cParent.getlNI("DATASOURCE"),cParent.getINI("USERID"),cParent.getINI("PASS
WORD"));
dbstmt = dbcon.SQLAllocStmtO;
/tExecute the SQL Statement
dbstrnt.SQLExecDirect(sqlString);
//Bind the data into arrays, column by column.
for (iLoop=0;iLoop < dbstrnt.SQLNumResultColsO.intValue0;iLoop++) {
data[iLoop] = new DbVarChar(100);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);
}




currVals = new VectorO;
allCatVal = new VectorO;
currCat= "";
while (dbstmt.SQLFetch0) {
if (currCat.equals("") )
currCat = data[0].toString0;
if (data[0].toString().equals(curr~at)) {
currV;~lc ~d(lF.l~ment(data[ I ].toString0.trim0+"&"+data[2].toString().trim0);
} else {
allCatVal.addElement(currCat+"="+Manipulation join('\t',currVals));
currCat= data[0].toStringO;
currVals.removeAllElementcO;
currV~lc ~ Flement(data[ I ] .toStringO.trim());
} }
allCatV~ ment(currcat+~ +Manipulationioin(~\t~currvals));
if (cParent.getINI("SERVERADDRESS ") .equals("none")) {
try {
address = InetAddress.getLocalHost().toStringO;
localHost= addr~cc c~lbstring(address indexOf("/")+l);
} catch(UnknownHostException e) {
localHost = "";
} else {
localHost = cParent.getINI("SERVERADDRESS");
}




outLine = "RH,000 1 ,col,"+"http://"+localHost+":"+String.valueOf(cParent.port)+",";
outLine += ","+cParent.getINI("PRODUCTTYPE")+","+Manipulationjoin('l',allCatVal);
routingTag = cParent.getINI("HUBURL");
inLine = routeData(outLine, routingTag);

//Strip the Response header off the line. 16 7

- CA 0220926~ 1997-06-27 f

if(inLine.lengthO > I l)
inLine = inLine.substring(12);
else
inLine = "";
} catch (DbSqlException e) {
if ( ! cParent.getlNI("DEBUG").equals("None")) {
System.out.println(" Error Trace: "+new DateO+" ");
System.out.println("SQL: "+sqlString);
e.printStackTraceO;
}




}
Il Shut everything back down.
dbstmt.SQLFreeStmt(Db.SQL_DROP);
dbcon.SQLDicconnectO;
dbcon.SQLFreeConnectO;
return inLine;
}




I**
* Re-route the data to the destination specified in the Routing Tag. Wait for and return a response.
*l
public String routeData( String outLine, String routingTag) {
Socket destination;
DataInputStream serverln;
DataOutputStream serverOut;
String Request;
String response;
String host;
URL destURL;
int whichPort;
try {
destURL = new URL(routingTag);
host = destURL.getHostO;
whichPort = destURL.getPortO;
if(whichPol L--O)
whichPort = cParent.DEFAULT_PORT;
destination = new Socket(host, whichPort);
try {
serverln = new DatalnputStream(destination.getInputStreamO);
serverOut = new DataOutputStream(destination.getOutputStreamO);
serverOut.writeBytes(outLine+"\n ");
response = WaitForResponse(serverIn);
return response;
}




catch (lOException e) { 16 8

- CA 02209265 l997-06-27

return "";
} catch (Exception e) {;
re~urn "Error";
} }
public String WaitForResponse(Dat~Tnrut.~tream inStream) {
boolean Body= false;
String line, CGIResponse;
CGIResponse = "";
try {
CGIResponse= inStream.readLirle0;
} ca~ch (IOException e) {
System.out.println("Error "+e+". Unable to obtain response.");
return "ERROR:0061Unable to obtain response from routed ~ tin~ti~n ~;
return CGIR~spon~e;
} }




169

CA 0220926~ 1997-06-27


/** Handles two vectors of Client objects, available
* and in-use. When the startClientO method is
* invoked, finds the next available Client object,
* puts it in the in-use vector, and kicks it off.
**l
import java.util.*;
import java.awt.*;
irnport java.net.*;
class ThreadHandler implements Runnable {
Vector availableThreads;
Thread handlerThread;
Cli~ntC~nnection tempThread;
SFServer cParent;
public ThreadHandler(SFServer argC) {
cParent = argC;
availableThreads = new Vector(5);
for(int iLoop=0;iLoop < 5; iLoop++) {
tempThread = new ClientConnection(this, cParent);
availableThr~A~ FI~rnent(tempThread);
}




public void startO {
if (handlerThread = null) {
handlerThread = new Thread(this);
handlerThread.setPriority(Thread.MAX_PRlORITY);
handlerThread.startO;
}




public void stopO {
if (handlerThread != null && handlerThread.isAliveO)
handlerThread.stopO;
handlerThread = null;
}




public void run() {
while(true);
}




public synchronized boolean startClient(Socket argSo) {
boolean foundOne = false;
boolean returnValue = true;
int howManyUsed;
for(Enumeration e=availableThreads.elements();e.hasMoreElementsO;){
tempThread=(ClientConnection)e.nextElementO;
if(!tempThread.inUse) {
tempThread.setSocket(argSo); 17 0

CA 0220926~ l997-06-27
f

((ClientConnection) tempThread).start();
foundOne = true;
break;
}
}




if(!foundOne) {
if(availableThre~r~c Ci7PO C 10) {
System.out.println("Exceeded the pool. Adding a new Thread...");
tempThread=new ClientConnec~ion(this, cParent);
tempThread.setSocket(argSo);
tempThread.inUse = true;
((ClientConnection) tempThread).startO;
availableThrea~lc ~ FlPment(tempThread);
else {
returnValue = false;
}




howManyUsed = 0;
for(Enumeration e2=availableThreads.elementsO;e2.hasMoreElements();){
if(((ClientConnection)e~ nPYtF.IPment0) jnUse)
howManyUsed++;
}




cParent.setStat(howManyUsed, availableThre~ ci7P0);
return returnValue;
}
}




171

-~ CA 0220926~ 1997-06-27 ~
-

import java.net.*;
import java.io.*;
import java.util.*;
import tcg.tools.*;
import jet.connect.*;
irnport java.awt.*;

/**************************************************
* Class: ClientConnection
* Written by: Brian Duncan
* Date:
* Purpose: This class handles a connection from
* a client. It receives and parses the request,
* does whatever processing it needs, in~lu~in~ ODBC,
* for~nulates and sends the response, and sl~ep~n~le itself.
**********************$***************************/
public class ClientConnection implements Runnable{
/IFlag including whether this thread is currently
//conversing with a client.
public boolean inUse;
//Socket passed from the server, connection from Client
protected Socket client;
//Datainput stream to the client
protected DataInputStream clientIn;
//Dataoutput stream to the client.
protected DataOutputStream clientOut;
//This thread.
protected Thread clientThread;
//Parsed-out routing tag (if any) from the client.
protected String routingTag;
//Data passed from the client
protected String data;
//lndicates whether or not the current request if for the
//Hub
protected boolean isHub;
protected SFServer cParent;
//The thread handler for this thread.
protected ThreadHandler handler;
//ODBC connection
protected DbDbc dbcon = null;
//ODBC Statement 17 2

- CA 0220926~ l997-06-27 _

protected DbStmt dbstrnt = null;

/**************************************************
* Constructor
**************************************************l
public CIientconnection(Thre~ r argC l, SFServer argC2 ) {
handler = argC l;
cParent = argC2;
//Make an ODBC conn~cti-~n using the Server's ODBC
//Environrnent.
dbcon= cParent.dbenv.SQLAllocConnectO;
dbcon.SQLConnect(cParent.getINI("DATASOURCE"),cParent getINI("USERID"),cParent.getINI("PASS
WORD"));

}
/**************************************************
* Start method for this thread.
**************************************************l
public void startO {
if (clientThread = null) {
//If thread hasn't been created, create it and start
l/it.
clientThread = new Thread(this);
clientThread.setPriority(Thread.NORM_PRIORITY);
clientThread.startO;
} else {
/lIf already thread here, resurne it.
this.resumeO;
}




/**************************************************
* Start method for this thread.
**************************************************l
public void stop0 {
if (clientThread != null && clientThread.isAliveO)
clientThread.stopO;
clientThread = null;
}




/**************************************************
* Suspend method for this thread
**************************************************/
public void suspendO {
clientThre~fl cllcp~n~l0;
}




/**************************************************
* Resume method for this thread.
**************************************************l

173

- CA 0220926~ 1997-06-27 ~'

public void resumeO {
clientThread.resumeO;
}
I**************************************************
* Run method for this thread. Checks to see if
* socket is valid, if it is, processes request,
* then suspends itself.
**************************************************/
public void runO {
String inLine, outLine;
//Loop forever
while(true) {
I/Has the socket for this connection been set?
if~client != null) {
inUse = true;
try {
/I read in the data
inLine = clientIn.readLineO;
// Parse out the string into routing tag and data.
if( ParseInput(inLine) ) {
//This request should be routed to another router.
outLine = routeData(data);
} else {
//This request should be processed by this router
outLine = processRequest(data);
}




//Uh-Oh, we had some kind of error
if( outLine.equals("Error") ) {
System.out.println("Unable to connect to client!");
} else {
//Pass the error to the client.
clientOut.writeBytes(outLine+"\n");
/ISave the error in the log file.
saveData(data, outLine);
} }
catch (lOException e) {
System.out.println("IOException with client - "+e.toStringO);
try {
client.closeO;
} catch(IOException e2) {}
} }
//Reset the Socket.
client = null; 174

-- CA 0220926~ 1997-06-27 _.

inUse = false;
//Suspend this thread. Server will resume it
//when it has a connection for it.
~hic cucpendo;
}




/**************************************************
* Sets the socket for the next connection. Also
* creates input and output streams.
**************************************************l
public void set~o~t(Socket argSo) {
client= argSo;
//Create input and output streams for this client.
try {
Il clientln = new n~t~Tnrl~tstream(new BuffereflTnrutctream(client~getTnru~streamo));
1/ clientOut = new DataOutputStream(new BufferedOutputStream(client.getOutputStreamO));
clientln = new DataInputStream(client.getInputStreamO);
clientOut = new DataOutputStream(client.getOutputStreamO);
}




catch (IOException e) {
try {
client.closeO;
} catch (IOException e2) {};
System.out.println("Exception while getting socket streams: "+e);
}
}




1*********************~****************************
* Takes the string passed in, parses out the routing
* tag and the data based on the ~ character.
**************************************************l
public boolean ParseInput(String sInput) {
int whereTilde;
//If the request contains a "~", there's a routing
lltag in it.
whereTilde = sInput.indexOf('~');
if( whereTilde == -I ) {
//No routing tag
routingTag= "";
data = sInput;
return false;
} else {
//There's a routing tag in it.
routingTag = sInput.substrin~ .~,whereTilde);
data = sInput.substring(whereTilde+ I );
//Check to see if it's a Hub request.
if (f~t::l c~lbstring(O,2).equals("RH"))
isHub = true;
else 17 5

-- CA 0220926~ 1997-06-27 ~-

isHub = false;
return true;
}




I**************************************************
* Re-route the data to the destination specified in
* the Routing Tag. Wait for and return a response.
****************************************~*********1
public String routeData( String outLine ) {
//Socket for the routed destination.
Socket destin~tion;
//DataInputStream for the routed rlestin~tior~
DataInputStream serverIn;
//DataOutputStream for the routed destin~tion
DataOutputStream serverOut;
//Response string from the routed destination
String response;
//Host name/IP address from destination.
String host;
URL destURL;
/IPort # from destination.
int whichPort;
//Attempt to connect to destination.
try {
destURL = new URL(routingTag);
host= destURL.getHostO;
whichPort = destURL.getPortO;
if(whichPort--0)
whichPort= cParent.DEFAULT_PORT;
destination = new Socket(host, whichPort);
try {
//Create input/output streams for destination
serverln = new DatalnputStream(new BufferedlnputStream(destination.getlnputStreamO));
serverOut= new DataOutputStream(new BufferedOutputStream(destination.getOutputStream()));
//Send the request to the destination
serverOut.writeBytes(outLine+"\n ");
serverOut-flushO;
//Wait for the response
response= WaitForResponse(serverln);
return response
} catch (lOException e) { 176

- CA 0220926~ 1997-06-27 ,-

try {
client.closeO;
} catch (lOException e2) {};
return "";
} catch (Exception e) {;
return "Error";
}




I**************************************************
* Sit and wait for a response from destin~tion
**************************************************l
public String WaitForResponse(Dat~Tnru'~tream inStream) {
boolean Body = false;
String line, CGlResponse;
CGIResponse = "";
try {
//Attempt to receive the response.
CGIResponse = inStream.readLineO;
} catch (lOException e) {
System.out.println("Error "+e+". Unable to obtain response.");
return CGlResponse;
}




I**************************************************
* processRequest(String) - This method deterrnines
* which request to process, and processes it
* appropriately.
**************************************************l
public String processRequest(String inLine) {
String header, type, id, outLine;
boolean hub;
//lf debug mode is set to high, show the request
//String.
if (cParent.getlNl("DEBUG").equals("High"))
System.out.println("Request: "+inLine);
outLine = "";
//Parse out the header from the request.
header = inT ine c~lhstring(0, l l);
//Parse out the type from the request.
type = header.substring(8).toUpperCase();
//Parse out the session id from the request.
id= inLine.substring(3,7); 177

~ CA 0220926~ 1997-06-27

//Parse out the Ini~i~1i7.or from the request.
Mf it's requesting to a hub, note that.
hub = header.substring(0,2).equals("RH") ? true: false;
//Strip out header info.
if(inLine.lengthO > I l)
inLine = inT.inP cllhstring(l2);
else
inLine = "";

Il Based on the type of request, call the ap~.. ~I)' iat~ method.
if(type.equals("CAT"))
outLine = processCAT0;
else if (type.equals("TYP"))
outLine = processTYP0;
else if (type.equals("HUB"))
outLine = processHUB0;
else if (type.equals("VAL"))
outLine = processVAL(inLine, hub);
else if (type.equals("SUB"))
outLine = processSUB(inLine, hub);
else if (type.equals("LST"))
outLine = processLST(inLine);
else if (type.equals("HOM"))
outLine = processHOM(inLine);
else if (type.equals("ADV"))
outLine = processADV(inLine);
else if (type.equals("PRO"))
outLine = processPRO(inLine);
else if (type.equals("COL"))
outLine = processCOLResponse(inLine);
else
return "RS,"+id+","+"ERR,"+"004jlnvalid request type.";
//lf response from handler method start with "ERROR",
Illt encountered an error (Probably ODBC).
if( outLine.startsWith("ERROR:")) {
outLine = "RS,"+id+","+"ERR"+","+outLine.substring(6);
} else
outLine= "RS,"+id+","+type+","+outLine;
Illf debug mode is set to high, show response string
if (cParent.getrNl("DEBUG").equals("High"))
System.out.println("Response: "+outLine);
return outLine;
}




I**************************************************
* Process the CAT request from the Client
**************************************************l
public String processCAT0 { 17 8

- CA 0220926~ 1997-06-27 ---

Vector categoryStuff, allCats;
String nextCategory;
allCats = new VectorO;
//Loop through all the categories in the XREF list.
for(Enumeration e = cParent.xrefCategory.elementsO; e.hasMoreElementsO;) {
categoryStuff= new Vector(5);
nextCategory = (String) ~ n~xtF~l~m.ont();
//Pull all info needed for this category into a vector.
categoryStllff ad-lF.lement(nextCategory);
categoryStnff ~rl(1Fl~oment(cparent.xrefHeader.get(nextcategory));
categoryStl-ff ~ Fl~ment(cparent~xrefLength.get(nextcategory));
categoryStllff ~ Fl~ment(cparent.xrefrype.get(n~ytc~fçgory));
categoryStllff~lrlFI~ment(cParent.xrefP~G.~lui~ get(n~YtC~tegory));
//Add tab-separated string of Category criteria.
allC~tc ~d-lF.lement(Manipulationjoin('\t',categoryStuff));
}




//Join all Cat criteria strings together separated by "I"
return Manipulation join('l',allCats);
}




I**************************************************
* Process the TYP request from the client.
**************************************************l
public String processTYP0 {
return cParent.getINI("PRODUCTTYPE");
}




I**************************************************
* Process the HUB request from the client.
**************************************************l
public String processHUB0 {
return cParent.getrNI("HUBURL");

}




I**************************************************
* Process the VAL request from the client.
**************************************************l
public String processVAL(String inLine, boolean isHub) {
String sqlString;
//Build the SQL String to query the database.
sqlString = buildValSQL(inLine, isHub);
//Connect to ODBC Driver
DbSqlException status = reConnect(isHub);
if(!(status = null))
return processERR(dbcon,dbstmt, status, "None");
return runValSQL(sqlString); 17 9

- CA 0220926~ 1997-06-27



I**************************************************
* Builds the SQL request string for the VAL request.
**************************************************l
public String buildValSQL(String inLine, boolean isHub) {

String sqlString;
Vector categories,queries;
if(isHub) {
//Build SQL for querying the Hub
int index = inLine.indexOf(',');
//Parse the Product type out of the string.
String productType = inLine.substring(0,index);
inLine = in~ ine ~bstring(index+l);
//Split the CAT request into Category-sized chunks
categories = Manip~ tion ~plit('l', inLine);
//Build the SQL String
sqlString = "SELECT t_category.category_name, t_value.value ";
sqlString += "FROM t_value, t_category ";
sqlString += "WHERE t_value.category_id = t_category.category_id and ";
sqlString += "t_category.product_id = "+productType+" and ";
sqlString += "t_category.category_name in ("'+Manipulationjoin("',"',categories)+"') ";
sqlString += "GROUP BY t_category.category_name, t_value.value ";
sqlString += "ORDER BY t_category.category_name, t_value.value";
} else {
//Build the SQL String for the Primary server
//Split the request into Category-sized chunks
categories = M~nir~ tion.split(~ inLine);
queries = new VectorO;
//Loop through the Categories requested
for(Enumeration e = categories.elements();e.hasMoreElementsO;) {
String nextCategory = (String) e.nextElement();
String nextColumn = (String) cPa-ent.xrefColumn.get(nextCategory);
//Build a SELECT statement for each category
String nextSQL = "SELECT distinct "';
nextSQL += nextCategory + "', ";
nextSQL += nextColumn + " FROM ";
nextSQL += cParent.getlNl("DBTABLE");
nextSQL += " WHERE "; 18 0

-~ CA 0220926~ 1997-06-27 -

nextSQL += nextColumn + " IS NOT NULL";
//If it's a CHAR type field, check for empty-string.
if (cParent.xrefColType.get(nextCategory).equals("CHAR"))
nextSQL += " and "+ nextColumn + " O "";
queries ~ F~lement(nextsQL);
//Join all select statements together with a "UNION"
sqlString = Manipulationjoin("\r\nUNION\r\n", queries);
}




return sqlString;
}




I**************************************************
* Runs the VAL SQL, parses the response into string.
**************************************************l
public String runValSQL(String sqlString) {
DbVarChar data[] = new DbVarChar[20];
Vector currVals, allCatVal;
String currCat= "";
try {

//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
//Bind the data into arrays, column by column.
for (int iLoop=0;iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++) {
data[iLoop] = new DbVarChar(100);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);
}




currVals = new Vector();
allCatVal = new VectorO;
//Pull in result set, row by row.
while (dbstmt.SQLFetch0) {
//Doing a control break on Category name
if (currCat.equals("") )
currCat = data[0].toString0.trim0;
if (data[0].toStringO.trim().equals(currCat)) {
//Add all the data from one particular category
//into the same vector.
if(data[ I ] = null)
currVals.addElement("");
else
currV~lc ~ Fl~rnent(data[ l ].tostring().trim());
} else {
//When the category changes, build a response
//for that category from the values collected.
allCatVal.addElement(currCat+"="+Manipulat8onjoin('\t',currVals));
currCat = data[0].toString0.trim0;

- CA 0220926~ 1997-06-27 ~-

currVals.removeAllElements();

//lf the result set contains a null value,
//replace it with empty-string
if(data[ I ] = null)
currValc ~d-lF.I-oment("");
else
currValc ad~lF.lenlent(data[ I ].toStringO.trimO);
}
}




//Build a response for the final category.
allCatV ~ lFlpnlent(currcat+~ +Manipulationioin(~tl~currvals));
} catch (DbSqlFY~eption e) {
return processERR(dbcon,dbstmt, e, sqlString);
}




1/ Shut everything back down.
dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
//Join all category values responses into the same string.
retum Manipulationjoin('l', allCatVal);
}
/**************************************************
* ~ocei~ts the SUB request from the Client
**************************************************/
public String processSUB(String inLine, boolean isHub) {
String sqlString;
sqlString = buildSubSQL(inLine, isHub);
//Connect to ODBC Driver
DbSqlException status = reConnect(isHub);

if(!(status = null))
return processERR(dbcon,dbstmt, status, "None");
//Sub SQL and val SQL return the same format of result
//set~ so why not use VAL's execute routine.
return runValSQL(sqlString);
}




I**************************************************
* Builds the SQL request string for the SUB request.
**************************************************l
public String buildSubSQL(String inLine, boolean isHub) {
Vector depValues, catParts;
String sqlString, category, column, prereq;
category= "";
if(isHub) { - 18 2

~ CA 0220926~ 1997-06-27
.

//Build SQL for querying the Hub
int index = inLine.indexOf(',');
/IParse the Product Type out of the Request string
String productType = inLine.substring(0,index);
inLine = inBine cubstring(index+l);
IlParse the Category name and values into two separate
//Elements
catParts = M~nirul~tion ~plit('=', inLine);
category = (String) catParts.elementAt(0);
//Parse the dependent values into a vector.
depValues = Manipulation.split("\t",(String) catParts.elementAt(l));
//Build the sql String.
sqlString = "SELECT t category.category_name, t_value.value ";
sqlString += "FROM t_value, t_category ";
sqlString += "WHERE t_value.category_id = t_category.category_id and ";
sqlString += "t_category.product_id = "+productType+" and ";
sqlString += "t_category.category_name = "'+category+"' and ";
sqlString += "t_value.prerequisite_value in ("'+Manipulationjoin("',"',depValues)+"') ";
sqlString += "GROUP BY t_category.category_name, t_value.value ";
sqlString += "ORDER BY t_category.category_name, t_value.value";
else {
//Build the SQL String for querying the primary server

//Parse the Category name and values into two separate
//Elements
catParts = Manipulation.split('=', inLine);
category = (String) catParts.elementAt(0);
/IParse the dependent values into a vector
depValues = Manipulation.split("\t",(String) catParts.elementAt(l));
//Get the actual column name for this category
column = (String) cParent.xrefColumn.get(category);
//Get the prerequisite column name for this category.
prereq = (String) cParent.xrefColumn.get((String) cParent.xrefPrerequisite.get(category));
//Build SQL string for the Primary Router
sqlString = "SELECT distinct "'+category+"', "+column;
sqlString += " FROM "+cParent.getlNl("DBTABLE");
sqlString += " WHERE "+column+" IS NOT NULL";
sqlString += " AND "+prereq+" in ("';
sqlString += Manipulationjoin("',"',depValues)+"')";
//lf this category is a CHAR type, don't allow 18 3

- CA 0220926~ 1997-06-27

//empties.
if (cParent.xrefColType.get(category).equals("CHAR"))
sqlString += " and "+ column + '' O '''';
return sqlString;
}
I**************************************************
* Processes the LST request from the Client
**************************************************l
public String processLST(String inLine) {
String sqlString;
sqlString = buil~T.ct~QL(inLine);

//Connect to ODBC Driver
DbSqlF.Yre~tion status = reConnect();
if(!(status = null))
return processERR(dbcon,dbstmt, status, "None");
return runLstSQL(sqlString);
}




I**************************************************
* Builds the SQL request string for the LST request.
**************************************************l

public String buildLstSQL(String inLine) {
Vector where, inSections, inTokens, inValues, columns;
String sqlString, needQuote, category, nextSection;
where = new VectorO;

//Split the request string into category-sized chunks
inSections = Manipulation.split('l', inLine);
//Build a column vector from the XREF Category vector.
columns = new VectorO;
for(Enumeration e = cParent.xrefCategory.elementsO; e.hasMoreElements(); )
colllmnc ~ Flpment(cparenLxrefcolummget((string)e n~tFl~mentO));
//Build the SELECT and FROM clauses of the SQL String
sqlString = "SELECT "+cParent.getINl("IDCOLUMN")+",";
sqlString += Manipulationjoin(",",columns);
sqlString += " FROM "+cParent.getINI("DBTABLE");
sqlString += " WHERE ";
//Loop through the Category Chunks, and build where clause
//for each one.
for(Enumeration e = inSections.elementsO; e.hasMoreElements(); ) {
nextSection = (String) e.nextElementO;
inTokens = Manipulation.split('=', nextSection),

-- CA 0220926~ 1997-06-27 ~-~

//Split the values for this category where into a
//vector
inValues = Manipul~tion cplit(~t', (String) inTo~nc elem~ntA.t(l));
category = (String)inTokens.elementAt(0);
.
//Determine if the value needs "'s around it based on
//The column type.
needQuote = cParent.xrefColType.get(category).equals("CHAR") ? ""':"";
//Build either a 'Between' or an 'In' clause, based
//on the type on category
if( cParent.xrefType.get(category).equals("Range"))
where ~ IFI~Pnt((String)cParent.xrefColumn.get(category) + " between "+needQuote+
inValues.elementAt(0) + needQuote+" and "+needQuote + inValues.elementAt(l) + needQuote);
else {
where ~(MFle~ent((string)cparent.xrefcolumn.get(category) + " in ("+needQuote +
Manipulationjoin(needQuote+","+needQuote,inValues) + needQuote+")");
}
}




//Join all the where clauses together, tack them on
//the end of the SQL String.
sqlString += lvl~nipul~tionioin(~ and ", where);
return sqlString;
}




/**************************************************
* Runs the LST SQL, parses the response into string.
**********************************~***************/
public String runLstSQL(String sqlString) {
DbVarChar data[] = new DbVarChar[20];
Vector outValues, outRows;
int iCount;
try {
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
//Bind the data into arrays, column by column.
for (int iLoop=O;iLoop < dbstmt.SQLNumResultCols().intValueO;iLoop++)
data[iLoop] = new DbVarChar(100);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);
}




outRows = new VectorO;
outValues = new VectorO;
iCount= 0;
//Loop through the Result set, row by row,
//until you reach the end, or read 50 rows,
//whichever comes first. 18 5

CA 02209265 1997-06-27

while (dbstmt.SQLFetchO && iCount <51) {
iCount++;
t/Assume the first column is the unique identifier.
//We" always call the first column "listnum",
I/So that the client applet can rely on it.
outV~Iut?s a~rlFlement(~listnum~+~ +data[0].toString0~trim0);
//Add the rest of the data to the vector.
for(int iLoop=l; iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++)
outV~hl~s ~drlF.l~ment((String)cParent xrefCategory.elementAt(iLoop-
l )+"="+data[iLoop] .tostring0.trim0);
//Join all the data for a row together, s~aL,d
//with "I"'s.
outRowc ~ Flement(Manipulationioin(~ outvalues));
outvalues~remove~llFl~nnentco;
}




} catch (DbSqException e) {
retum processERR(rlbcon~lhstmt~ e, sqlString);
}




//Release the ODBC ~ e~L
dbstmt SQLFreeStmt(Db.SQL_CLOSE);
if (!outRows.isEmpty0)
mf there was something in the result set,
//Join all the row data strings together into a
//big string.
return Manipulationjoin("ll", outRows);
else
//If there was nothing in the result set, return
//empty-string.
return "";
}




1******************~*******************************
* Processes the HOM request from the Client
************************~*************************1
public String processHOM(String inLine) {
RandomAccessFile fTemplate, fOutHTML;
Vector columns, vNameValues, names, sections;
Hashtable values;
String sqlString, line;
boolean keepIt;
String needQuote, TemplateExt, oString;
//Determine template extension. We will use this as
lla basis to ~l~tt nnine whether to build an HTML page,
//or a get request.
TemplateExt= cParent.getINI("HTMLTEMPLATE");
186

- CA 0220926~ 1997-06-27
~ ,

if( TemplateFY~ in~l~xOf(" ") > 0) {
TemplateExt = TemplateFYt cllhstring(Templ~teFYt indpyof(~ll)+l)~touppercaseo;
} else
TemplateExt= "HTM";
//If the Template file has an extension of "HTM" or "HTML",
IfConfli~ion~lly build the HTML file. Otherwise, formulate
lla CGI 'GET' request.
if( TemplateExt.equals("HTM") 1I TemplateExt.equals("HTML")) {
//Check to see if the file already exists.
keepIt= isCurrentHTML(inLine, TemplateExt);

if(!keepIt) {

/IWe need to create a new HTML file.
try {
fTemplate = new RandomAccessFile(cParent.getlNI("HTMLTEMPLATE"), "r");
columns = getHTMLTemplateTags(fTemplate);
//Determine if the ID column is Char, if so,
//put quotes around it.
needQuote = cParent.getlNI("IDTYPE").equals("CHAR") ? ""':"";
//build the SQL String based on all the
//unique columns in the template file.
sqlString= "SELECT "+Manipulationjoin(',',columns);
sqlString += " FROM "+cParent.getINI("DBTABLE");
sqlString += " WHERE "+cParent.getlNI("IDCOLUMN")+"="+needQuote+inLine+needQuote;
//Connect to ODBC Driver
DbSqlException status = reConnect();
if(!(status = null))
return processERR(dbcon,dbstmt, status, "None");
//Run HOM SQL, parse response into a hashtable.
try {
values = runHomHTMLSQL(sqlString, columns);
catch (DbSqlException e) {
return processERR(dbcon, dbstmt, e, sqlString);
}




//Create new HTML file handle.
fOutHTML = new RandomAccessFile("htmV/"+inLine+"."+TemplateExt,"rw");
//Reset the position of the Template file back
llto the top
fremplate.seek(O);
IlPut the appropriate data into the
//new HTML file. 18 7

- CA 0220926~ 1997-06-27 -

buildHTMLFile(fTemplate, fOutHTML, values);

//Close the two files.
fTemplate.closeO;
fOutHTML.closeO;
retum cParent.getlNI("HTMLDIRECTORY")+inLine+"."+TemplateExt;
catch(lOException e) {
System.out.println("Couldn't read the template file.");
retum "ERROR:0041Couldn't read the template file.";
}




} else {
retum cParent.getlNl("HTMLDlRECTORY")+inLine+"."+TemplateExt;
} else {
//Build a Get Request URL.
//Deterrnine and open the template file.
try {
fTemplate = new RandomAccessFile("template.get", "r");
line = "first";
columns = new VectorO;
names = new VectorO;
//Chug through the template file, finding all column tags, and putting them in a basket.
while( line != null) {
line = fr~mpl~te readLine0;
if (line != null && line.trimO.length() > 0) {
sections = Manipulation.split("=",line);
nam~s ~d~FI~ment((String)sections.elementAt(0));
colnmnc ~dAFlement((String)cectionc elementAt(l));
}
}




fTemplate.closeO;
needQuote = cParent.getlNl("lDTYPE").equals("CHAR") ? ""':"";
sqlString = "SELECT "+Manipulationjoin(',',columns);
sqlString += " FROM "+cParent.getlNl("DBTABLE");
sqlString += " WHERE "+cParent.getlNl("lDCOLUMN")+"="+needQuote+inLine+needQuote;
//Connect to ODBC Driver
DbSqlException status = reConnect();
if(!(status = null))
retum processERR(dbcon,dbstmt, status, "None");
try { 1 8 8

-- CA 0220926~ 1997-06-27 --
- '

vNameValues = runHomCGlSQL(sqlString, names);
oString =
cParent.getINl("HTMLDIRECTORY")+cParent.getlNI("HTMLTEMPLATE")+"?"+Manipulation join("&
",vNameValues);
oString = oString.replace(",'+');
return oString;
} catch(DbSqlException e) {
fTemplate.closeO;
return processERR(dbcon, dbstmt, e, sqlString);
}
} catch(IOException e) {
System.out.println("Couldn't read the template file.");
return "ERROR:0041Couldn't read the template file.";
}
}




I**************************************************
* Deterrnines whether or not the HTML file requested
* in the HOM request is there, and if so, if it's
$ still current.
**************************************************/
public boolean isCurrentHTML(String inLine, String TemplateExt) {
Date date, oldDate;
int htmlRefresh;
boolean keepIt = true;
File oldFile;
//Open a file object to the Existing HTML file.
oldFile = new File("html//"+inLine+"."+TemplateExt);

I/ls it already created?
if( oldFile.exists0) {
//Should we consider the page static?
if( Integer.valueOf(cParent.getlNl("HTMLREFRESH")).intValueO > 0) {
//If no HTMLREFRESH setting has been specified,
//Default it to I hour.
if(cParent.getINI("HTMLREFRESH ").equals("none"))
htmlRefresh= I;
else
htmlRefresh = Integer.valueOf(cParent.getlNI("HTMLREFRESH")).intValueO;
//Compare the current date/tirne with the existing
//HTML file's date/time.
oldDate = new Date(oldFile.lastModifiedO);
date = new DateO;
if(oldDate.getDateO != date.getDate()) {
//The two days are different, create a new 18 9

- CA 0220926~ 1997-06-27 .-


//file.keepIt= false;
else if ((date.getHoursO - oldDate.getHoursO) > htmlRefresh) {
/rrhe time between the old file and he new file
//is greater than the allowed amount. Create
//a new file.
keepIt = false;
else {
//Everything checks out Keep the file.
keepIt = true;
}




} else {
//HTMLRefresh setting = 0. This means, keep it if
l/it exists at all. This is used for static pages.
keepIt = true;
}




} else {
//The file has never been created. We must create it
keepIt = false;
}




return keepIt;
}




/**************************************************
* Pulls all the column tags out of the template
* htrnl file.
**************************************************/
public Vector getHTMLTemplateTags(RandomAccessFile fTemplate) throws IOException {
Vector sections;
Vector columns = new VectorO;
Enumeration eFragments;
String line, nextColumn;

try {
//Chug through the template file, fnding all column
//tags, and putting them in a basket.
while( (line = fremplate.readLine0) != null) {
sections = M~nipul~tion cplit(~ sEEKDBcoL=\llll~line);
eFragments = sectionC ele~nentsO;
//Skip first element;
if( eFragments.hasMoreElementsO )
eFragmPn~c n~ytFlemento;
while( eFr~gm~tc h~cMoreElementso ) {
nextColumn = (String) eFMgrn~ntc n~ytFlemento;
nextColurnn = nextColumn.substring(0,nextColnmn ind~xOf(""));
if(!columns.contains(nextColumn))
colnmnc ~r1Flement(nextcolumn);
}
}




} catch(IOException e) {
//Re-Th~ow the exception, because we want the called method to
190

_ CA 0220926~ 1997-06-27

/Ihandle it.
throw e;
return columns;
}




I**************************************************
* Runs the SQL for the HOM request (HTML version),
* returns a hashtable
**************************************************l
public Hashtable runHomHTMLSQL(String sqlString, Vector columns) throws IOException {
DbVarChar data[] = new DbVarChar[20~;
Enumeration eColumns;
Hashtable values;
try {
/IExecute the SQL St~tPnlpnt
dbstmt.SQLExecDirect(sqlString);
IlBind the data into arrays, column by column.
for (int iLoop=0;Loop < dbstmt.SQLNumResultColsQintValue0;iLoop++) {
data[iLoop] = new DbVarChar(100);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);
}




/IBuild a hashtable from the columns and corresponding values.
values = new HashtableO;
eColumns = columns.elementsO;
IlOnly one row in the result set, so no need for a
//Loop per row.
dbstmt.SQLFetchO;
for (int iLoop=0;iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++)
values.put( (String) eColumns.nextElement(), data[iLoop].toStringO.trim0 );
//Close the ODBC connection.
dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
} catch(DbSqlException e) {
throw e;
return values;
}




I**************************************************
* Runs the SQL for the HOM request (CGI version),
* returns a Vector
**************************************************l
public Vector runHomCGISQL(String sqlString, Vector names) throws DbSqlException {
DbVarChar data[] = new DbVarChar[20];
String sName, sValue; 191

- CA 0220926~ l997-06-27 --'

Vector vNameValues;
tr,Y {
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
//Bind the data into arrays, colurnn by column.
for (int iLoop=0;iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++) {
data[iLoop] = new DbVar{ har(100);
dbstrnt.SQLBindCol(iLoop+l, data[iLoop]);

//Fetch the first and only row in this result set
dbstrnt.SQLFetchO;
vNameValues = new VectorO;
//Loop through the colurnns in the result set row,
//making name/value pairs out of them.
for (int iLoop=0;iLoop < dbstmt.SQLNumResultCols0.intValue0;iLoop++) {
sName = (String)n~mPs elPmPnt~t(Loop);
sValue = data[iLoop].toString0.trim0;
vNameVal-lPc ~ pment(sName+~ +svalue);
}




dbstmt.SQLFreeStmt(Db.SQL C~OSE);


} catch (DbSqlException e) {
throw e;
return vNameValues;
}




/**************************************************
* Build the new HTML file based on the Template file
**************************************************/
public void buildHTMLFile(RandomAccessFile fTemplate, RandomAccessFile fOutHTML, Hashtable
values) throws IOException {
String line, nextColumn;
int index;
try {
/IGo back through the template file, re-find the
l/tags, and copy over the template code to the
//new HTML file, swapping the tags for data.
while( (line = fremplate.readLine0) != null) {
index = line.indexOf("!--SEEKDBCOL");
while (index > - I ) {
nextColurnn = line.substring(index+l4,1ine.indexOf("",index+14));
line = line ~nhstring(o~index-
l)+values.get(nextColurnn)+line snbstring(line.indexOf("",index+14)+4);

192

CA 0220926~ 199i-06-27 __

index = line in~exof(~ -sEEKDBcoLll);
}



fOutHTML.writeBytes(line+ \n );

} catch (IOException e) {
throw e;
}




//This method pl ocesses the ADV request.
public String processADV(String inLine) {
DbVarChar data[] = new DbVarChar[80];

Vector where, inSections, inTokens, inValues, columns;
Vector outRows;
String sqlString, n~Yt~ection nextColumn, nextSQL, category;
Enumeration eSecti~nc;
String productType;
int index;
where = new VectorO;
index = inLine inf~YOf(',');
productType = inLine.substring(0,index);
inLine = inLine.substring(index+ I );
inSections = Manipulation.split('l', inLine);
sqlString = "SELECT ad_text, ad_url ";
sqlString += "FROM t_advertisement, t_value, t_category ";
sqlString += "WHERE t_advertisement.product_id = "+productType+" and ";
sqlString += "t_advertisement.category_id *= t_value.category_id and ";
sqlString += "t_adverticPm~nt value *= t_value.value and ";
sqlString += "t_advertisement.category_id *= t_category.category_id and ";
sqlString += "(t_advertisement.category_id IS NULL";
eSections = in~ectjonc elementsO;

while(eSectiorlc h~cMoreElementsO) {
nextSection = (String) eSections.nextElementO;
inTokens = Manipulation.split('=', nextSection);
inValues = Manipulation.split('\t', (String) inTokens.elementAt(l));
category = (String)inTokens.elementAt(0);
where.addElement(" (t_category.category_name = "'+category+"' and t_value.value in ("'+
Manipulationjoin("',"',inValues) + "'))");
}




if (!where.isEmpty()) {
sqlString += " or "; 193

- CA 0220926~ 1997-06-27

sqlString += Manipulationjoin(" or ",where);
}




sqlString += ")";
try {
//Connect to ODBC Driver
DbSqlException status = reConnect(true);

if(!(status--null))
return processERR(rlbcon llhst~nt, status, "None");
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
t/Bind the data into arrays, column by column.
for (int iLoop=0;iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++) {
data[iLoop] = new DbVarChar(80);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);

outRows = new VectorO;
while (dbstmt.SQLFetch0) {

outRows.addElement(data[O].toString().trim()+'\t'+data[l].toStringO.trimO);
} catch (DbSqlException e) {
return processERR(dbcon,dbstmt, e, sqlString);

dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
return Manipulationjoin("l", outRows);

}




//This method processes the PRO request.
public String processPRO(String inLine) {
DbVarChar data[] = new DbVarChar[50];

Vector where, inSections, inTokens, inValues, columns;
Vector outRows;
String sqlString, nextSection, nextColumn, nextSQL, category, tempSQL;
String productType;
int index;
Enumeration eSections;
where = new VectorO; 19 4

--- CA 0220926~ 1997-06-27 __


index = inT.ine indexOf(',');

productType = inT.ine cnbstring(0,index);
inLine= inT ine ~lbstring(index+l);
inSectjon~ = Manipulation.split('l', inLine);
sqlString = "SELECT url ";
sqlString += "FROM t_server ";
sqlString += "WHERE ";
tempSQL= "t_server.server_id IN ";
tempSQL += " (SELECT t_server.server_id ";
tempSQL += "from t_server, t_category, t_value ";
tempSQL += " where t_server.server_id = t_value.server_id and ";
tempSQL += " t_category.category_id = t_value.category_id and ";
tempSQL += " t_category.product_id = " + productType+" and ";
tempSQL += " t_server.product_id = " + productType+" and ";
eSection~ = in~ecti-~n~ elementsO;
while(eSections.hasMoreElementsO) {
n~Yt~ection = (String) eSection~ npxtElemento;
inTokens = l~nip~ tion.split('=', neYt!~ection);
inValues = Manipulation.split('\t', (String) inTokens.elementAt(l));
category = (String)inTokens.elementAt(0);
where.~lF.l~rnent(tempSQL + "t_category.category_narne = "'+category+"' and
t_value.value in ("'+ Manipulationjoin("',"',inValues) + "'))");
}




if(!where.isEmptyO) {
sqlString += Manipulationjoin(" and ",where);
} else {
sqlString += " t server.product id = " + productType;
}
try {
//Connect to ODBC Driver
DbSqlException status = reConnect(true);
if(!(status = null))
return processERR(dbcon,dbstrnt, status, "None");
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
//Bind the data into arrays, column by column. 19 5

CA 0220926~ 1997-06-27


for (int iLoop=0;iLoop < dbstmt.SQLNumResultColsO.intValue0;iLoop++) {
data[iLoop] = new DbVarChar(100);
dbstmt.SQLBindCol(iLoop+l, data[iLoop]);
}




outRows = new VectorO;
while (dbstmt.SQLFetch0) {
outRowc ~d-lFlPment(data[0].toString().trim0);

} catch (DbSqlException e) {
return processERR(dbcon,dbstmt, e, sqlString);
}




dbstmt.SQLFreeStmt(Db .SQL_CLOSE);

return Manipulationjoin("l", outRows);
}




public String processCOLResponse(String inLine) {

DbValue tempValue;
DbInteger DBCatID, DBServerID;
DbChar DBValue, DBPrerequisite;
String sqlString, category, serverURL, serverID, categoryID;
String productType;
Vector categories, tempVector, values, vBoth;
Enumeration eCat, eVal;
int index;
String returnString = "Updated.";
index = inLine.indexOf(',');
if(index > 0 ) {
serverURL = inLin~ cubs~ring(0,index);
inLine = inLine.substring(index+2);
} else
serverURL= "";
index = inLine.indexOf(',');
if(index > 0 ) {
productType = inT ine cubstring(0,index);
inLine = inLine.substring(index+ l );
} else
productType= "";
sqlString = "SELECT server_id from t_server where url = "'+serverURL+""';
//Connect to ODBC Driver
196
try {

CA 0220926~ 1997-06-27 .~
t ,

DbSqlException status = reConnect(true);

if(!(status = null))
return processERR(dbcon,dbstmt, status, "None");
//Execute the SQL Statement
dbstmt.SQLExecDirect(sqlString);
serverID = "";
//Pull out the Server ID
if~dbstmt.SQLFetchO) {
tempValue = new DbValueO;
dbstmt.SQLGetData(l ,tempValue);
serverID = tempValue toStringO;
retumString= "Updated.";
Mf it came back with a server ID, Cool, delete all
//their current values out of the value table.
dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
sqlString = "delete from t_value where server id = "+serverID;
dbstmt.SQLExecDirect(sqlString);
} else {
//Otherwise, create new server record with a~.l,. up, iat~
t/URL, and product type.
//Determine next ID code.
dbstmt.SQLFreeStmt(Db.SQL CLOSE);
sqlString = "SELECT max(server_id)+l FROM t_server";
dbstmt.SQLExecDirect(sqlString);
if(dbstmt.SQLFetchO) {
tempValue = new DbValueO;
dbstmt.SQLGetData(l ,tempValue);
serverID = tempValue.toString();
dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
sqlString = "INSERT into t_server (server id, product_id, server_name, url) ";
sqlString += "VALUES ("+serverlD+","+productType+","'+"Created: "+new
DateO.toStringO+"',"'+serverURL+"')";
returnString = "Created. ";
dbstmt.SQLExecDirect(sqlString);
dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
}




dbstmt.SQLFreeStmt(Db.SQL_CLOSE);

197

CA 0220926~ 1997-06-27 __

~ //Ok, now trudge through the passed in COL request, ~arsing
llout category names, and associated values and prerequisite values.
categories = Manipul~tion cplit(~ inLine);
eCat = categories.elementsO;
while(eCat.hasMoreElementsO) {
tempVector= Manipulation.split('=', (String) eC~t nPyt~nlento);
category = (String) tempVector.elementAt(0);
values = Manipulation.split(~t', (String) tempVector.el~m~nt~t(l));
/tFind out the category ID that corresponds with the category name
//parsed out.
sqlString = "SELECT category_id FROM t_category ";
sqlString +="WHERE category_name = "'+category+""';
sqlString +="and product_id = "+productType;
dbstmt.SQLExecDirect(sqlString);
categoryID = null;
if (dbstmt.SQLFetch0) {
tempValue = new DbValue();
dbstmt.SQLGetData(l ,tempValue);
categoryID = tempValue toStringO;
}




dbstmt.SQLFreeStmt(Db.SQL_CLOSE);

if(categoryID!=null) {
/tSet up a statement to do multiple inserts
dbstmt.SQLPrepare("INSERT INTO t_value values (?,?,?,?)");

DBCatlD = new DblntegerO;
DBServerID = new DbIntegerO;
DBValue = new DbChar(100);
DBPrerequisite = new DbChar(100);
dbstmt.SQLBindParameter(l,Db.SQL_PARAM_INPUT, DBServerlD);
dbstmt.SQLBindParameter(2,Db.SQL_PARAM_INPUT, DBCatlD);
dbstmt.SQLBindParameter(3,Db.SQL_PARAM_INPUT, DBValue);
dbstmt.SQLBindParameter(4,Db.SQL_PARAM_INPUT, DBPrerequisite);
DBCatID.set(categoryID .toString());
DBServerID.set(serverID toStringO);
for (eVal = values.elementsO; eVal.hasMoreElementsO;) {
vBoth = Manipulation.split('&',(String)eVal.nextElementO);
DBValue.set((String) vBoth.elementAt(0));
if(vBoth.sizeO ---2)
DBPrerequisite.set((String) vBoth.elementAt( I ));
else 19 8

CA 0220926~ 1997-06-27 r~

DBPrereqllicite ~et("");
dbstrnt.SQT .FY~C~I~e();
} else {
return "ERROR: Category not found in Hub Database";
}




dbstmt.SQLFreeStmt(Db.SQL_CLOSE);
}




} catch (DbSqlException e) {
return processERR(dbcon,dbstmt, e, sqlString);
}




dbstrnt.SQLFreeStrnt(Db.SQL_CLOSE);
retum returnString;
}




public DbSqlException reConnectO {
return reConnect(false);
}




1/ Method to test the current ODBC connection.
1/ The Parameter is used to determine whether this
// is a Hub or not.
public DbSqlException reConnect(boolean argB)
try {
dbstmt = dbcon.SQLAllocStrntO;
if(argB)
dbstmt.SQLExecDirect("select 2 from t_server");
else
dbstmt.SQLExecDirect("select 2 from "+cParent.getINI("DBTABLE"));
dbstmt.SQLFreeStrnt(Db.SQL_CLOSE);
} catch(DbSqlException e) {
try {
dbcon.SQLFreeConnectO;
} catch(DbSqlException e2) {
}
try {
dbcon = cParent.dbenv.SQLAllocConnect();
dbcon.SQLConnect(cParent.getINI("DATASOURCE"),cParent.getINI("USERlD"),cParent.getINI("PASS
WORD"));
dbstmt = dbcon.SQLAllocStrnt();
Syst~m out println("ODBC: Reconnected");
} catch(DbSqlException e3) {
return e3;
} 199

_ CA 0220926~ 1997-06-27

return null;
}




public String processERR(DbDbc dbcon, DbStmt dbstmt, DbSqlException e, String sqlString) {
String returnValue;
returnValue = "ERROR:"+"0051"+e.toStringO;
dbstmt.SQLFreeStmt(Db.SQL CLOSE);
if(!cParent.getINI("DEBUG").equals("None")) {
System.out.println(" ErrorTrace: "+new DateO+" ");
System.out.println("SQL: "+sqlString);
e.printStackTraceO;
}




return returnValue;
}




ll Take input string, output string, pull data into a string that will be
//saved to the end of the log file.
public void saveData(String ArgS 1, String ArgS2) {
String oDestination, oType, oDate, oTime, oListings, oClientAddress;
Date d = new DateO;
int count = 0;
oClientAddress = Manipulation.padSpaces(client.getInetAddressO.toString0, 30);
oDestination = Manipulation.padSpaces(routingTag, 22);
oType = ArgSl.substring(8,11);
oDate =
Manip~ tion p~A7~ros(String.valueOf(d.getMonth()+1),2)+"/"+Manipulation.padZeros(String.valueOf(d.
getDateO),2)+"/"+String.valueOf(d.getYear());
oTime =
Manipulation.padZeros(String.valueOf(d.getHoursO),2)+":"+Manipulation.padZeros(String.valueOf(d.get
MinutesO),2);
oType = oType.trimO.toLowerCase0;
if(oType.equals("lst")) {
count = Manipulation.countOccurrences(ArgS2, "11");
ll If there are no "ll"'s in the string, check to see if that's
ll because there was only one listing.
if(ArgS2.1ength() > 12)
count++;
oListings = Manipulation.pad_eros(String.valueOf(count), 4);
} else {
oListings = " ";
}




try {
//Go to the end of the file
cParent.lOut.writeBytes(oClientAddress);
cParent.lOut.writeBytes(oDestination); 2 0 0

CA 0220926~ l997-06-27
f

cParent. IOut.writeBytes(oType);
cParent.lOut.writeBytes(oDate);
cParent.lOut.writeBytes(oTime);
cParent.lOut.writeBytes(oListings);
cParent.lOut.writeBytes('~r\n");
catch (IOException e) {
System.out.println("Unable to write to Usage.log\n");
}
}




201

Representative Drawing
A single figure which represents the drawing illustrating the invention.
Administrative Status

For a clearer understanding of the status of the application/patent presented on this page, the site Disclaimer , as well as the definitions for Patent , Administrative Status , Maintenance Fee  and Payment History  should be consulted.

Administrative Status

Title Date
Forecasted Issue Date Unavailable
(22) Filed 1997-06-27
(41) Open to Public Inspection 1998-08-27
Dead Application 2000-06-27

Abandonment History

Abandonment Date Reason Reinstatement Date
1999-06-28 FAILURE TO PAY APPLICATION MAINTENANCE FEE

Payment History

Fee Type Anniversary Year Due Date Amount Paid Paid Date
Application Fee $300.00 1997-06-27
Registration of a document - section 124 $100.00 1997-06-27
Owners on Record

Note: Records showing the ownership history in alphabetical order.

Current Owners on Record
THE COMPUTER GROUP, INC.
Past Owners on Record
DUNCAN, BRIAN
EVANS, GARY
TELFORD, ROBERT
Past Owners that do not appear in the "Owners on Record" listing will appear in other documentation within the application.
Documents

To view selected files, please enter reCAPTCHA code :



To view images, click a link in the Document Description column. To download the documents, select one or more checkboxes in the first column and then click the "Download Selected in PDF format (Zip Archive)" or the "Download Selected as Single PDF" button.

List of published and non-published patent-specific documents on the CPD .

If you have any difficulty accessing content, you can call the Client Service Centre at 1-866-997-1936 or send them an e-mail at CIPO Client Service Centre.


Document
Description 
Date
(yyyy-mm-dd) 
Number of pages   Size of Image (KB) 
Description 1997-06-27 201 6,254
Claims 1997-06-27 21 635
Drawings 1997-06-27 7 193
Cover Page 1998-09-10 1 55
Abstract 1997-06-27 1 20
Representative Drawing 1998-09-10 1 10
Assignment 1997-06-27 2 84
Correspondence 1997-09-12 1 21
Assignment 1997-09-17 6 154
Correspondence 1997-09-17 1 29
Correspondence 1997-09-29 1 23
Prosecution-Amendment 1997-10-21 7 162