A Web-Based Object Oriented System
for Information Management

John W. Collins, Rolando Blanco,
Christos Douligeris, Jay Jacobs

University of Miami
Department of Electrical and Computer Engineering email: {collins, rblanco, christos, jjacobs}@ece.miami.edu

Abstract

This paper describes Oyster, an object oriented system for structuring and presenting information on the Web. Implemented in Perl on top of a Relational Database System, Oyster combines the set oriented tools for accessing data from relational systems with the navigational oriented syntax of object oriented technology. Clients can interact with the system through OQL, Oyster's Object Oriented Query Language. No assumption is made regarding the language for implementing clients; a number of Java clients are currently under development to augment the web-based interface of Oyster.

1. Introduction

Oyster is an object oriented system for managing and presenting complex, structured information, using the world-wide web as its primary interface. Oyster's web interface is augmented by Java [1] applets for interactive graphical querying. Oyster builds on top of a low level implementation inside a relational database [4] and provides a foundation for a higher level of manipulation in terms of objects, methods, attributes and relations. The web interface to the data is insulated from the underlying relational database, simplifying the data maintenance process.

Unlike other web interfaces to database systems, Oyster combines the set-oriented tools for accessing data from relational systems with the navigational-oriented syntax of object oriented technology. Clients can interact with the system through OQL, Oyster's Object Oriented Query Language. OQL provides a well-defined, powerful interface to a hierarchically organized structure of object types.

Oyster was originally designed to support access to and management of a diverse set of scientific data. From the beginning all efforts were made to maintain the generality of the system without assumption about a particular format of the underlying data. As a result Oyster can serve as a shell (pun intended) for developing dynamically configurable systems for data presentation on the web, ranging from corporate intranets to scientific/environmental data management.

Why Objects?

The benefits of object-oriented programming have been well-known for a number of years, as attested by the large-scale shift toward this style of designing and writing programs. These benefits include encapsulation, reusability, abstraction and inheritance [8]. Objects are defined to be instances of one (or more) types, or classes, which conceptually cluster objects with a common set of attributes and operations. Classes, in turn can be defined as subclasses of one (or more) superclasses. A special class OBJECT defines the root of the type hierarchy; this is the only class which is not a subclass of another class. Note that in this document the terms class and type are used interchangeably.

The real benefits of the object-oriented approach come from the ability to organize functionality with the object classes, and inherit functionality from abstract base classes to specific refinements. Subclasses can redefine, or override the implementation for a function provided by a base class, so that different classes can have shared functionality but implemented using different procedures. We use the term operation to refer to a general functionality, and the term method to refer to a particular implementation for a given class. Applying an operation to an object amounts to invoking the corresponding method defined for one of the object's direct or inherited types.

A class defines the attributes which its instances should possess; the values generally vary from instance to instance. A class also defines methods which implement the operations applicable to its instances. These features (i.e., attributes and methods) are inherited to the instances of all (direct and indirect) subclasses of the class.

Benefits for Web Page Generation

Working at the higher level provided by Oyster, its methods, and the OQL language yields significant leverage over the alternative of low-level cgi scripting, just as programming in a high level language is more efficient than programming in assembler code. Moreover every class receives all the functionality provided by its base classes, so the cost of developing a method is spread over a much larger set of potential callers.

Organization

This paper is organized as follows: Section 2 details the design and unique features of Oyster as well as implementation issues. Section 3 highlights the methods in Oyster as a preamble to Section 4, which presents a language for querying objects, called OQL. Current applications of Oyster are presented in Section 5. Finally some conclusions and future extensions are discussed.

2. Design and Implementation

Oyster combines the features of object-oriented programming with the traditional features of relational database systems, namely, set oriented and concurrent access to data, persistence, and error recoverability.

Oyster uses the world-wide web as its primary interface. Each object possesses the ability to display itself to the web, using a DISPLAY method which is multiply defined within the class hierarchy. Different types of objects invoke these different methods to implement the DISPLAY operation. These methods are instances of HTML_METHOD, a subclass of the METHOD class, whose instances output HTML pages when invoked.

HTML methods are augmented by Java applets, which share a common socket-based connection to Oyster's object-oriented database system. The applets communicate through this socket using a querying language called OQL, which was developed specifically for accessing the objects and methods in Oyster. OQL is described in detail in Section 4.

Object Type Hierarchy

Everything in Oyster is an object, including classes, relations and attributes. This design decision was motivated by the desire to provide meta-level constraints on the representation, such as typing constraints on relations. Having classes as full-fledged objects facilitates dynamic construction of the type hierarchy, making Oyster a truly flexible system.

Object Attributes and Relations

Compound objects, such as sets, assemblies and lists, are represented in Oyster using relations. In fact, the class hierarchy is implemented by establishing SUBCLASS_OF relations between pairs of CLASS objects.

Below is a partial list of the relation types in Oyster:

SUBCLASS_OF(<CLASS>, <CLASS>)
INSTANCE_OF(<OBJECT>, <CLASS>)
PART_OF(<OBJECT>, <OBJECT>)
DOMAIN_TYPE(<RELATION>, <CLASS>)
RANGE_TYPE(<RELATION>, <CLASS>)
DOMAIN_MULTIPLICITY(<RELATION>, <NUMBER>)
RANGE_MULTIPLICITY(<RELATION>, <NUMBER>)
Each binary relation has a designated inverse relation, which represents the same object pairs but in the reverse order. Only one of an inverse pair of relations is physically stored; the other is derived using its inverse by swapping the order of its objects.

Attributes can be seen as established relations between objects and values; for example, color. Attributes differ from general relations in two ways. First, attributes are usually functions which map to a unique value, and functions are a subclass of relations. Second, the values represented by attributes are generally not instantiated in the system as objects; i.e., they do not have an identity. Otherwise, attributes behave similarly to other relations.

Nearly all of the relations in Oyster are binary. Support is provided for higher order relations through composition of multiple binary relations.

Inheritance

Classes have a special instance called the prototype, which contains the default values for attributes for the instances of the class. When a new object is created, attributes are gathered from the prototypes in the class hierarchy. Some attributes are specified as editable, indicating that the default value may be overridden.

It is also possible to inherit attributes without default values. As mentioned previously, attributes and relations in Oyster are strongly typed. In addition to type information relations specify the multiplicity of their related objects and values. This information can be used to determine which relations are required and which are optional. After a new object has been created, a form is constructed to solicit values for those attributes and relations registered to classes from which the new object derives. Figure 1 shows the form generated for a new instance of the PERSON class.

Object Name: CHRIS
FIRST_NAME:
LAST_NAME:
ADDRESS:
EMAIL:
OFFICE:
WORK_PHONE:
HOME_PHONE:
Figure 1: Attribute Inheritance

The type information for objects is not statically cached; instead it is derived from the type hierarchy at run-time. This facilitates the dynamic typing feature described below.

Operations and Methods

Applying an operation to an object requires first determining which method should be used to implement the operation. The method provided by the most specific class in the object's type list is the one selected. Specificity here is determined by the transitive closure of the subclass relation, a partial order relation. Ties represent ambiguous method inheritance, and must be avoided by overriding multiply-inherited operations at join classes. Once the correct method has been identified, it is invoked by "requiring" the corresponding Perl [11] source file and calling the top level function that implements the method. Dynamic binding allows us to determine at run-time which method should be used to implement a requested operation. Thus applying the same operation to a list of objects of different types can result in different method invocations for each object.

Methods can be called either for their return values or for side-effects, or both. Return values, if non-NULL, generally take the form of a string or a list of strings; each string typically identifies an object or attribute value, or contains tab-separated columns of objects and attributes. Typical side effects include modifying the contents of the database or file system, or printing HTML to the web browser. A method whose primary function is to output HTML is called an HTML_METHOD, a subclass of the METHOD class.

Dynamic Typing

Unlike other object-oriented approaches, Oyster treats type as a relation, independent of object identity. Specifically, an INSTANCE_OF relation is established between the instance being typed and the class representing the type. This distinction has two advantages. First, it supports multiple (direct) typing of objects, without the need for creating a join class for each distinct case. This is particularly beneficial, given that it is impossible to anticipate all meaningful combinations of classes to which an object might belong.

Second, it allows for type evolution of an object without loss of identity. In other words, an object can join a class, withdraw from a class, or refine its type without losing its attributes and relations to other objects. Dynamic typing allows an object to evolve over time, without having to destroy and recreate the object at each transition along the way. For example, an infant becomes a child, then an adolescent, then an adult, while most of her attributes are carried across these stages of development.

3. Predefined Methods

While it is intended that each application of Oyster would provide its own set of operations and methods, a core set of predefined methods are implemented to provide some basic functionality for the built-in classes. Below is a partial list of implemented methods, organized by class; it is intended to give the reader a sense of the system's functionality.

Object Methods:

TO_STRING()
Returns a text string identifying the object (i.e., its name).
DISPLAY()
Displays in HTML format all the object's attributes and relations.
PURGE()
Eliminates all references to the object.
CLONE(NAME)
Creates a shallow copy of the object.
GET_TYPES()
Returns a list of the classes to which the object belongs.
EDIT_ATTRIBUTES()
Displays a form for editing the object's attributes.
EDIT_RELATIONS()
Displays a form for editing the object's relations.
GET_ATTRIBUTE(ATTRIBUTE)
Returns the value (if any) of the given attribute.
FILTER(ATTRIBUTE, VALUE)
Returns the object if it has the given attribute-value pair, or NULL otherwise. Value is optional.
SET_ATTRIBUTE(ATTRIBUTE, VALUE)
Sets the value for the given attribute.
SET_RELATION(RELATION, OBJECT)
Establishes a relation with another object.

Class Methods:

INSTANTIATE(NAME)
Creates a new instance of the class.
REFINE(NAME)
Creates a new subclass of the class.
GET_SUBCLASSES()
Returns a list of the subclasses of the class.
GET_SUPERCLASSES()
Returns a list of the superclasses of the class.
GET_INSTANCES()
Returns a list of the instances of the class.
MAP_INSTANCES(OPERATION, ARGS)
Applies the operation to the instances of the class.
EDIT_PROTOTYPE()
Displays a form for editing the class prototype's attributes and relations.

Attribute Methods:

ESTABLISH_ATTRIBUTE(OBJECT, VALUE)
Adds an attribute-value pair for the object.
GET_OBJECT_TYPE()
Returns the base type of object for which the attribute is valid.
GET_VALUE_TYPE()
Returns the data type of the attribute's values.
GET_OBJECTS()
Returns a list of the objects having a (non-null) value for the attribute.

Relation Methods:

ESTABLISH_RELATION(OBJECT, OBJECT)
Sets up a relation between the two named objects.
GET_OBJECT1_TYPE()
Returns the base type for the first object.
GET_OBJECT2_TYPE()
Returns the base type for the first object.
GET_OBJECT2(OBJECT)
Returns a list of objects having the relation to the given object.
GET_INVERSE_RELATION()
Returns the inverse relation for the given relation.

File Methods:

GET_CONTENTS()
Returns the file's contents.
DELETE()
Deletes the file and purges the file object.
MOVE(FILENAME)
Relocates the file in the file system.
COPY(FILENAME)
Creates a copy of the file object.
APPEND(STRING)
Appends the string to the end of the file.

Method Methods:

PARSE()
Displays the source code for the method, with clickable links to called functions and callers of functions.
APPLY(OBJECT, ARGS)
Invokes the method on the given object and arguments.

4. OQL

OQL is a syntactically simple but highly expressive language designed to interact with Oyster. A C++ [9] flavored language, OQL serves as DML (Data Manipulation Language). OQL combines the navigational style of object oriented languages with the set oriented functionality of relational algebra. Figure 2 gives a glimpse of OQL's syntax.

Figure 2: Formal Definition of OQL Syntax

query ::= oql_stmt | query oql_stmt
oql_stmt ::= op_list terminator
op_list ::= object_id | op_list connector member_access
connector ::= '.' | '@'
member_access ::= attribute_id | function_id '(' arglist ')'
function_id ::= operation_id | scope_op method_id | class_id scope_op method_id
arglist ::= empty | op_list | arglist ',' op_list
scope_op ::= '::'
terminator ::= empty | '\n' | ;
empty ::= ''

Note: All object_id, attribute_id, operation_id, method_id and class_id are terminal STRINGS

An interpreter for OQL was developed using yacc [7] and the formal description shown in Figure 2. The result of the parse is perl code ready to be executed by Oyster. Using OQL, client programs interact with Oyster through a socket-based [10] interface.

The principal construction is the operation invocation. An operation can return either nothing, a value, or one or more objects. As shown in Figure 3, if more than one object is returned the following operation in the sentence can be applied to each one of the objects or once to the set that contains all objects. The former behavior is obtained with the . (dot) notation and is referred to as the 'map' application. The latter behavior, known as the 'set' application, is specified with the @ (at) notation. Figure 3 explains the semantics for some selected OQL statements.

Figure 3: OQL's Semantics
OBJECT
Returns OBJECT
OBJECT.ATTRIBUTE
Returns OBJECT.GET_ATTRIBUTE(ATTRIBUTE)
OBJECT.OPERATION(ARGS)
Calls OBJECT.METHOD(ARGS), where METHOD=CLASS::OPERATION for some CLASS of OBJECT, if such a METHOD exists; else returns NULL
OBJECT.OP1(ARGS1).OP2(ARGS2)
Passes results of OBJECT.OP1(ARGS1), one at a time, to OP2(ARGS2); if OP1 returns NULL, OP2 is never called
OBJECT.OP1(ARGS1)@OP2(ARGS2)
Passes results of OBJECT.OP1(ARGS1), as a SET, to OP2(ARGS2); OP2 is called once regardless of the results of OP1

Operations of the relational algebra (join, cartesian product, project, and select) have been implemented and are used in the set application. The basic methods presented in Section 3 as well as the methods implemented for user-defined classes, are runnable from this language independently of the language used to implement such methods. Methods can be scoped to bypass the dynamic binding mechanism.

Note that the execution of an OQL statement that involves several set and/or map applications can be viewed as a pipe process in the sense of UNIX pipes [6]: the output of an operation is used as input to the next operation in the pipe. OQL operations receive not only input but arguments, which can themselves be the result of pipe processes; therefore it is possible for several pipes to exist at a given time. And because map applications do not assume any order in the execution of the operations, the computation of the OQL statements can be naturally parallelized following a SIMD (Single Instruction Multiple Data) schema [3].

5. Applications

Oyster has its origins in an application called OSIMS: the Ocean Status Information Management System [2] [5]. OSIMS is the result of an ongoing multidisciplinary research and development effort within the College of Engineering of the University of Miami, conducted in cooperation with scientists from the Rosentiel School of Marine and Atmospheric Science (RSMAS).

OSIMS is an integrated information management tool that facilitates environmental science research and environmentally-related management tasks. It provides a graphical interface to an object oriented database containing geographically referenced environmental data. OSIMS is online at:

http://osims.eng.miami.edu/

OSIMS offers a database system coupled with a set of visualization capabilities for viewing maps, time series, etc., and for performing graphical point-and-click queries on landmarks overlayed on dynamically generated maps. Other functionality in OSIMS includes:

As a second application, the web site for the College of Engineering of the University of Miami is being re-implemented using Oyster.

6. Conclusions

General Experience

We considered several programming languages as candidates for implementing Oyster. Perl has proven to be an excellent choice as it strikes a balance between the efficiency of compiled code and the flexibility and power of scripting languages. We expected to reach a level of complexity where Perl was no longer able to perform and a compiled language would be necessary; we are still waiting.

The object oriented approach is reminiscent of declarative programming, where the user specifies what is wanted but not how it is to be implemented. There are practically no conditional branches required for any of the methods; instead of performing case splits, the object hierarchy determines which implementation to use for each operation.

Future Extensions

Oyster is still under development, we are currently working in a number of extensions including better tools for creating and managing objects. Java classes are being developed to support hierarchical selection of object classes and instances. This functionality will be used in a number of client applets, including a highly interactive object editor and a graphical querying facility.

OSIMS is also evolving to take full advantage of Oyster's capabilities. Version 2.0 of OSIMS will be fully integrated with Oyster.

References

[1] Arnold, K., Gosling, J. The Java Programming Language. Addison-Wesley, May 1996.
[2] Blanco, R., Jacobs, J. Ocean Status Information Management System: Data on the WWW. In Proceedings of Oceans 96 MTS/IEEE. pp 1557-1560. September 1996.
[3] Burns & Davies. Concurrent Programming. Addison-Wesley, 1993
[4] Codd, E.F., A Relational model for large shared data banks. Communication of the ACM, Volume 13, Number 6, June 1970, pp 377-387.
[5] Douligeris, C., Collins, J., Iakovou, E. Development of OSIMS: An Oil Spill Information Management System. In Second International Oil Spill Research and Development Forum. pp 774-781. London, May 1995. Also in: Spill Science and Technology Bulletin, 1996.
[6] Kernighan, B.W., Pike, R. The Unix Programming Environment. Prentice Hall, 1993.
[7] Mason, T., Brown, D. Lex & Yacc. O'Reilly & Associates, 1990.
[8] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., Lorensen, W. Object-Oriented Modeling and Design. Prentice Hall, 1991.
[9] Stroustrup, B. The C++ programming language. Addison-Wesley, 1986.
[10] Stevens, R. Unix Network Programming. Prentice Hall, 1990. URL: http://www.noao.edu/~rstevens
[11] Wall, L., Christiansen, T., Schwartz, R. Programming Perl. O'Reilly & Associates, 2nd Edition, 1996.





Return to Top of Page
Return to Posters Index