Adaptation Strategies in Componentware - CiteSeerX

1 downloads 0 Views 151KB Size Report
tween the involved parties is supported by dedicated soft- ware systems. They offer a set of general technical services, like version and access control for project ...
Adaptation Strategies in Componentware Klaus Bergner, Andreas Rausch, Marc Sihling, Alexander Vilbig Technische Universit¨at M¨unchen Institut f¨ur Informatik Arcisstrasse 21, 80290 Munich, Germany [email protected] Abstract In the context of componentware, there are several dif¯ component. They ferent strategies to adapt a given ge¯neric differ in the necessary prerequisites and the achieved quality of the resulting specific component with respect to reliability, efficiency and reusability. In this paper, we discuss a number of conceivable adaptation strategies for components, like wrapping, composition, or inheritance. We use the graphical user interface of a computer aided engineering system as an example to illustrate the transfer of a selected adaptation strategy into practical system development.

1 Introduction Component-oriented software development promises to allow the production of well-structured software systems using generic, truly reusable building blocks. However, it is still an open question if this promise can be kept, as it requires the existence of a universal set of configurable components which are prepared to be used in a specific context [BRSV98b]. Practical experience with today’s components suggests a different situation—most components cannot be used “out of the box”, but have to be adapted and tailored to the specific requirements and the given technical environment. Obviously, these observations apply especially to large, complex legacy components which have not been built according to componentware design criteria. In this paper, we argue that besides predetermined configuration, component adaptation is also a very useful strategy for embedding reusable components into new systems. Adaptation addresses the problem that many reusable com This paper originates from the research in the project A1 “Methods for Component-Based Software Engineering” at the chair of Prof. Dr. Manfred Broy, Institut f¨ur Informatik, Technische Universit¨at M¨unchen. A1 is part of “Bayerischer Forschungsverbund Software-Engineering” (FORSOFT) and supported by Siemens AG, Department ZT.

ponents have to offer very generic functionality in order to be useful in many situations, while specific systems require components with very specific properties and functionality. In order to specialize generic components and to adapt them to a given situation, there are different conceivable adaptation strategies which have to be applied in the context of an overall system architecture. In Section 2, we first introduce an application example, namely, a large computer aided engineering application based on a three-tier architecture and a common product model. It illustrates different possibilities for the use of generic components which have to be adapted to the chosen architecture and design. Section 3 then presents a number of different adaptation strategies, like wrappers, dedicated adaptor components, and inheritance, from a more abstract point of view. Finally, in Section 4, a combination of selected techniques is applied to provide a solution for the graphical user interface of the application example. The conclusion contains an evaluation of the proposed solution as a trade-off between potential benefits and necessary efforts as well as an outlook to other, more advanced uses of adaptation strategies.

2 Application Example: An Engineering System In today’s engineering, many experts of different areas collaborate to work on a given project. The necessary coordination of the distributed work and communication between the involved parties is supported by dedicated software systems. They offer a set of general technical services, like version and access control for project documents, and a set of specific business-oriented services for tasks like simulation, product model validation, and visualization. Examples for such systems arise in various engineering disciplines, from CAE platforms [Ste97, ATL] to CASE tools [BRS98]. Because of the distributed usage of these systems, they are usually organized according to a three-tier architecture [Den91, BMR+ 96] as shown in Figure 1.

Client1

sists of a tree view that shows elements of an hierarchical product model as illustrated by the left side of Figure 2. Once an element of the product model is selected by the user, its content is visualized in a different area of the user interface as illustrated by the right side of Figure 2.

Clientn

...

Network

OtherTechnical Services

AccessControl Service

VersionControl Service

SimulationService

ValidationServcie

OtherBusinessOrientedServices

CommonProduct Model

DatabaseManagement

Figure 1. Overall Architecture of a Computer Aided Engineering System

The presentation layer of such an architecture comprises a set of graphical user interfaces (GUI) on distributed clients which allow users to browse and visualize the actual product model, like, for example, the construction plan of a car under development. Moreover, the GUI clients are a means to access the functionality provided both by the specific business-oriented services and the general technical services of the application layer. Thereby, the user is able to manipulate the common product model using the businessoriented services with support and control of the available technical services. The current state of the project and auxiliary data is stored by components in the database layer of the architecture. In the context of a computer aided engineering system based on the previously described architecture, there are a number of possible reuse scenarios involving the adaptation of existing generic components. As an example, we could require the version control service to record the current da te as well as the name and employee number of the person who edited the current version of a given document. An existing generic version control component, however, might only support to record the date, the name and a textual comment. Thus, it is necessary to adapt this generic component to the specific requirements, for example by supplying the employee number as a special textual comment. A more interesting reuse scenario involves the presentation layer: A very important graphical user interface for systems based on a common product model is a so-called Product Model Browser. Oftentimes, such a browser con-

Figure 2. A Product Model Browser For the implementation of such a browser, we could require different user interface components to represent different views on the common product model: A Product Model Structure View which visualizes the hierarchical structure of the product model and a Product Model Content View which is able to show the content of a given element of the product model. These two specific components should be integrated into the Product Model Browser. Additionally, we expect the browser to serve as a central entry point for other user interface components of the system, responsible for performing tasks like archiving or editing selected parts of the product model. These components should be able to request information about the currently selected elements of the product model by means of a dedicated Product Model Selection Manager as part of the browser. Given the previous requirements and design guidelines, it is sensible to reuse a commercially available generic tree view component for the implementation of the Product Model Structure View within the browser. However, it will be necessary to adapt this component for the specific interactions with the other components of the browser, for instance the Product Model Content View and the Product Model Selection Manager. Before proposing a solution to this problem in Section 4, we first present a number of conceivable adaptation strategies for components from a more general point of view.

Specific Component Generic Component

Generic Import Interface 1 Generic Import Interface j

Generic Component

Generic Export Interface1

Specific Import Interface 1

Specific Import Interface m

Specific Export Interface1

Generic Export Interfacek

Specific Export Interfacen

Figure 3. Wrapping a Generic Component

3 Adaptation Strategies

Currently, a large variety of GUI components are commercially available. An efficient implementation of the Product Model Browser comprises the (re-)use of generic GUI components like tree or list views. Ideally, these components already exist and have been successfully employed in other projects, thereby proving their high quality with respect to efficiency, reliability, etc. If a suitable component does not already exist, however, it is still possible to specify the expected behavior as well as an according generic interface and have it developed from scratch. This approach lacks the desired properties of a proven solution but allows to source out a defined part of the project to a dedicated team of developers. Moreover, it may be possible to reuse the developed components in a different context later. The generic interface of the used GUI components requires their adaptation to the specific context. Although the concept of adaptation comprises any modifications of a component that lead to a desired behavior, in this section we only consider the transition from generic to specific behavior. This transition is typical when adapting generic GUI components as necessary during the implementation of the Product Model Browser GUI. In the context of componentware, there are several different strategies to adapt a given generic component. They differ in the necessary prerequisites, like having access to the source code or not, the amount of development effort needed and the achieved quality of the resulting specific component with respect to reliability, efficiency or reusability. Although we mention a number of particularly interesting strategies, a more complete set of development guidelines will be part of a collection of process patterns for a pattern-based development process model suited to componentware [BRSV98a]. Note that the graphical notation used to illustrate the presented strategies in the following sections is an extended version of the standardized Static Structure Diagrams of the Unified Modeling Language UML [OMG99] (cf. [BRSV98b]).

3.1 Wrapper

Wrapping a generic component means embedding it in a specific component as outlined in Figure 3. The generic component requires certain services from its environment in order to provide the generic functionality. This fact is represented in Figure 3 by sets of corresponding interfaces (Generic Import Interface 1 to j and Generic Export Interface 1 to k). A GUI component, for example, needs access to a dedicated drawing area before its paint operation may be called. The wrapping specific component, on the other hand, requires its own set of services from the environment (Specific Import Interface 1 to m), so that its specific functionality may be used (Specific Export Interface 1 to m). A GUI component for the display of a structured data model, for example, has to be able to locate the data before any draw operations may be performed. The mapping between specific and generic functionality as well as the provision of required services has to be accomplished by the wrapping component as indicated by its grey background in Figure 3. The resulting implementation efforts range from a simple delegation of interface calls, as in the case of a Display Refresh operation, to a complex series of actions involving several generic interfaces, as necessary in the case of a Display Product Model Element operation, for example. Note that the wrapped generic component is not visible to the environment of the wrapping specific component. Any required services that are provided by the environment have to be duplicated in corresponding interfaces of the specific component. The same applies obviously to generic functionality that is to be offered to the environment. In some cases this technique may result in additional implementation overhead but in ensures the complete encapsulation of the wrapped generic component which is a desired property in many component-oriented architectures.

Generic Component

Adaptor Component

Generic Import Interface 1

Generic Export Interface1

Specific Import Interface 1

Generic Import Interface j

Generic Export Interfacej

Specific Import Interface m

Generic Export Interface1

Generic Import Interface 1

Specific Export Interface1

Generic Export Interfacek

Generic Import Interface k

Specific Export Interfacen

Figure 4. Composition of a Generic and an Adaptor Component

3.2 Composition with Adaptor Component Composition relies on specific adaptor components to translate between generic and specific functionality as represented in Figure 4. The adaptor component is combined with the generic component by connecting the sets of compatible generic interfaces (Generic Import and Export Inteface 1 to j and Generic Import and Export Interface 1 to k). Similar to the previous description of the wrapper strategy (see Section 3.1), the adaptor component may have to provide the required services to the generic component in order to use its functionality. However, composition also allows the environment to provide some of these services or to use generic functionality as the generic component remains visible to the outside. Superficially, this seems to be a fundamental difference to the wrapper strategy, allowing the distinction between a black-box and a white-box adaptation strategy. Note, however, that it still possible to aggregate both generic and adaptor component within a third wrapper component which only exposes the specific interfaces. It is therefore obvious that composition represents a refined development technique with respect to the wrapper strategy. It properly encapsulates the mapping between specific and generic functionality within a single component. This allows to easily exchange both generic and adaptor component later if extended or more efficient versions become available.

3.3 Adaptation Interface Many generic components are already prepared to be used in a specific context. They possess so-called adaptation interfaces (Adaptation Import Interface 1 to r and Adaptation Export Interface 1 to s in Figure 5) which provide defined entry points for the inclusion of specific behavior. A typical example are event interfaces of GUI components which allow to register so-called listener components for a set of generic events. The listener components provide hook methods that will be called by the GUI component when a certain event, like the selection of a tree node, for example, happens. This in turn triggers the execution of

Adaptation Import Interface 1

Generic Component

Generic Import Interface 1

Adaptation Import Interface r

Generic Import Interface j

Adaptation Export Interface1

Generic Export Interface1

Adaptation Export Interfaces

Generic Export Interfacek

Figure 5. A Generic Component with Adaption Interfaces

specific functionality, like a request for actual model data which is to be displayed in a different part of the GUI. It is furthermore conceivable that adaptation interfaces allow to delegate certain method calls of generic interfaces transparently to specific components as illustrated in Figure 6 by a grey arrow connecting the respective interfaces. This results in a substitution of specific behavior for generic behavior which remains completely transparent to other components connected to the generic component. Note that such a potentially powerful adaptation mechanism has to be used with great care: It is fairly easy to violate the original specification of the system in a way that is hard to detect during runtime.

3.4 Inheritance Inheritance on the code-level is essentially the same development technique as offered by object-orientation. It allows to add new interfaces in order to implement specific functionality which relies on generic functionality offered by the base component. Furthermore it is possible to modify generic behavior by re-implementing the generic interfaces in the derived component. These facts are illustrated by Figure 7 which uses an UML-like notation to represent the inheritance relation. In principle, inheritance allows to adapt a component by just implementing the additional specific functionality while reusing existing generic functionality. However, it is also possible to redefine generic behavior in a way that violates the original specification. Other components that rely on this functionality (which is still visible to the environ-

Specific Import Interface 1

Specific Component

Generic Component

Adaptation Export Interface1

Adaptation Import Interface 1

Generic Import Interface 1

Specific Import Interface m

Adaptation Export Interfaces

Adaptation Import Interface r

Generic Import Interface j

Specific Export Interface1

Adaptation Import Interface 1

Adaptation Export Interface1

Generic Export Interface1

Specific Export Interfacen

Adaptation Import Interface r

Adaptation Export Interfaces

Generic Export Interfacek

Figure 6. Delegation of Generic to Specific Behavior by Adaptation Interfaces ment of the derived component) are thus liable to fail. Moreover, inheritance may only be applied in the context of componentware if the corresponding implementation language supports this concept naturally. Although inheritance could be realized by wrapping in theory, this does not seem to be a practical approach.

3.5 Re-implementation Re-implementation is obviously the most drastic variant of adaptation: The generic component only serves as an example or a template for the development of the specific component (see Figure 9). Generic Component

Generic Import Interface 1 Generic Import Interface j Generic Export Interface1 Generic Export Interfacek

4 Exemplary Adaptation Regarding the implementation of a Product Model Browser as introduced in Section 2, we propose an initial wrapping approach: The different areas of the GUI (see Figure 2) may be regarded as specialized views on the underlying product model, namely the hierarchy of the product model and the introspection of product model data. Like already mentioned in Section 2, we consequently introduce specific GUI components like Product Model Structure View or Product Model Content View which are associated to the component Common Product Model in a typical model/view relation. The management of user interaction regarding selection state, currently available actions etc. is carried out by dedicated manager components (Product Model Selection Manager and Product Model Action Manager). They are associated both to the existing view components and to the common product model as controllers following the MVC design pattern [GHJV95]. These different relations between the participating components are illustrated in Figure 8. Product Model Content View

Product Model Structure View Specific Import Interface 1

Specific Component

Generic Import Interface 1

Specific Import Interface m

Generic Import Interface j

Specific Export Interface1

Generic Export Interface1

Specific Export Interfacen

Generic Export Interfacek

Figure 7. A Specific Component Inherits from a Generic Component

Some parts of the generic component may be reused in a ’copy-and-paste’ fashion if the original source code is available. However, even if the source code is not available, it is still beneficial to study the interface and behavior of the generic component. This may provide valuable suggestions for the design and implementation of the specific component in question.

Controller/View

Controller/View

Controller/View

Model/View

Controller/View

Model/View

Product Model Action Manager

Product Model Selection Manager

Model/Controller

Common Product Model

Model/Controller

Figure 8. High Level Design of the Proposed Solution The view components are specific in the sense that they

Generic Component

Generic Import Interface 1

Specific Component

Specific Import Interface 1

Generic Import Interface j

Specific Import Interface m

Generic Export Interface1

Specific Export Interface1

Generic Export Interfacek

Specific Export Interfacen

Figure 9. Reimplementing a Generic Component may only be attached to a Common Product Model which they query for data once an update of the view is requested. Furthermore they provide information about user interaction only in terms of the underlying specific data model, e.g. with notifications like product model element selected or product model element expanded. To implement this specific behavior, the view components rely on internal generic components that support the intended presentation and interaction style. As an example we consider the component Product Model Structure View which is likely to use a generic tree view to display the structure of a given product model database, thereby effectively wrapping the internal tree view. The necessary adaptation functionality is encapsulated in a separate adaptor component Product Model Structure Adaptor which is composed with the TreeView component as proposed by the according adaptation technique in section 3.2. It is actually Product Model Structure Adaptor that offers application specific functionality via the interface PM StructureView which is exposed to the environment by Product Model Structure View as shown in Figure 10. The depicted interfaces are discussed in detail in the following parts of this section.

Product Model Structure View

Tree View

TreeView TreeListener

Product Model Structure Adaptor

Interface TreeView Properties // distinguished tree nodes TreeNode rootNode TreeNode selectedNode ... // visual appearance Style lineStyle Size nodeSpacing ... // behavior related Bool allowsSelection Bool allowsEditing ... Methods // supply application context setDrawingArea(Area a) // define the area to draw ... // structural modifications insertNode(TreeNode p, TreeNode c) // insert new node as child deleteNode(TreeNode n) // delete node from tree ... // navigation facilities TreeNode getChildNode(TreeNode p) // get first child of parent TreeNode getNextNode(TreeNode n) // get next sibling of node ... // attribute related operations setImage(TreeNode n, Image img) // specify visual representation setUserData(TreeNode n, UserData d) // associate app. specific data ... // notification related operations, see below addListener(TreeListener t) // specify component to be notified removeListener(TreeListener t) // don’t notify component any more ... End TreeView

PM_StructureView

Figure 10. Design of Product Model Structure View

The generic interface TreeView of the Tree View component is likely to offer general functionality as outlined below:

Additionally, a generic tree view component is liable to offer a notification mechanism to inform other components about user interactions like selection of tree nodes or expansion of branches. A possible implementation would require the interested components to provide a suitable callback interface as outlined below1 :

1 There are obviously other conceivable implementations like an eventbased scheme, for example.

Interface TreeListener Properties // no properties necessary Methods // callback operations, called by Tree View nodeSelected(TreeNode n) // if tree node was selected nodeDeselected(TreeNode n) // if node was deseleted nodeExpanded(TreeNode n) // if node was expanded nodeCollapsed(TreeNode n) // if node was collapsed ... End TreeListener

server() in order to receive updates once the data model has changed. The described initialization sequence is illustrated by Figure 11 which omits the method-call delegation from Product Model Structure View to Product Model Structure Adaptor to keep the diagram simple. TreeView

ProductModel StructureAdaptor

Common ProductModel

ProductModel Browser

setProductModel(CommonProductModel)

Note that the interfaces are described in an implementation-independent way although it should be easy to translate them into languages like Java or C++. The interfaces of well-known existing tree views like JTree from the Swing package [Jav98] or CTreeCtrl of the Microsoft Foundation Classes [Mic96] (MFC) may also be easily mapped to the given descriptions. In contrast to the generic functionality of the tree view, the proposed specific component Product Model Structure View resp. Product Model Structure Adaptor provide an interface with application-oriented functionality as outlined below: Interface PM StructureView Properties ProductModel currentPM // currently displayed product model PMDataElement selDataElement // currently selected data element update() // called when model changed ... Methods setDrawingArea(Area a) // define the area to draw setProductModel(ProductModel m) // init view with product model update() // called when model changed update(PMDataElement) // called when element changed ... End PM StructureView

The implementation of Product Model Structure View as realized by the Product Model Structure Adaptor component has to translate calls of specific operations into sequences of generic operations of the interface TreeView. The operation setProductModel, for example, has to traverse the product model structure using the navigation and data retrieval operations provided by Common Product Model and build a corresponding tree structure by using the according operations of TreeView (insertNode(), etc). While constructing the tree it is also necessary to associate the created tree nodes with references to the corresponding data elements using setUserData() and to provide intuitive graphical representations suited to the data in question (setImage()). Finally, the Product Model Structure Adaptor registers itself as a tree listener with the tree view (addListener()) in order to process user interactions and as an observer to its model via addOb-

getData()

Repeatuntil tree completed

insertNode(TreeNode,TreeNode)

Placeholderfor asetof model-specific query operations

setImage(TreeNode,Image) constructTree()

setUserData(TreeNode,UserData) Internal operationof adaptor addListener(TreeListener)

addObserver(self)

Figure 11. Exemplary Initialization Sequence Once Product Model Structure Adaptor has registered itself with the tree view, it receives notifications about user interactions which are then translated into applicationspecific notifications within the callback operations of TreeListener. The corresponding specific notification interface as used by a controller component like Product Model Selection Manager, for example, could be specified as: Interface PM StructureListener Properties // no properties necessary Methods // callback operations called by Structure View // if car series was selected seriesSelected(PM Series s) engineSelected(PM Engine e) // if engine was selected chassisSelected(PM Chassis c) // if chassis was selected // if image was selected imageSelected(PM Image i) seriesRequested(PM Series s) // if car series was expanded engineRequested(PM Engine e) // if engine expanded seriesRequested(PM Chassis c) // if chassis was expanded ... End PM StructureListener

Any component interested in these applicationspecific notifications has to implement the interface PM StructureListener and register itself with Product Model Structure View resp. Product Model Structure Adaptor. A selection manager, for example, could listen to the selection of an image series and subsequently instruct a

content viewer component to display the according thumbnails. This exemplary notification scenario is illustrated by Figure 12. User

TreeView

ProductModel StructureAdaptor

ProductModel SelectionManager

ProductModel ContentView

mouseClick()

Internal operationof ProductModel Selection Manager

nodeSelected(TreeNode)

seriesSelected(PM_Series)

updateSelectionState()

displayThumbnails(PM_Series)

Figure 12. Exemplary Notification Sequence Apart from this direct translation from specific to generic behavior, Product Model Structure View could also offer more complex specific functionality like the definition and activation of filters that determine the amount of displayed product data. It is conceivable, for example, to display only parts of the product model hierarchy or to display only information about engines with a certain name. This leads to an expansion of the interface PM StructureView with operations like setFilter( PM Filter f ), applyFilter() or removeFilter() that require more complex translation functionality. It may be necessary, for example, to clear the current tree view and construct a new display hierarchy according to the applied filter. The proposed solution and application examples are obviously not complete in the sense that more examples of advanced functionality like multiple selection or notifications before a branch is expanded (in order to cancel the expansion if the current user has only restricted access to product data), for example, have not been accounted for. The necessary translation process between specific and generic functionality has also only been sketched on an exemplary level. Nevertheless, it should be quite straightforward to map the presented ideas and abstract design principles on a concrete design and implementation.

5 Conclusion In this paper, we have shown how component adaptation techniques can be utilized to convert general, reusable components into application-specific components that fit into the overall architecture of a three-tiered system. The proposed wrapping and composition approach provides encapsulation of the reused components, emphasiz-

ing the separation of concerns between the different tasks of building a high-quality generic GUI component and the specific handling of structured application data. Due to this decoupling, the wrapped generic component may be replaced or changed later on, necessitating changes only within the adaptor component. Compared to the wrapper strategy, component inheritance seems to be an inferior strategy. On the one hand, it implies an unnecessarily strong coupling between components, as programmers have to know not only the interface, but also the source code of the original component. In most cases, changes of the original component require a reworking of the adapted component as well. On the other hand, inheritance is less convenient, as the interface of the adapted component has to encompass the interface of the original component. Quite similar, direct modification of a component’s code (in case it has been provided) is usually not a feasible solution, as it doesn’t provide any encapsulation at all. Based on the experience gained with the application example, it seems that component-oriented design principles are especially suited to applications that present structured data for interaction with the user in multiple specialized views. There are many generic GUI components available that may be adapted using the techniques mentioned in this paper. The resulting architecture allows for an extremely flexible design of the GUI in which all relevant parts (product model, generic view, translation functionality) are easily exchangeable. As already mentioned in Section 2, we think that the proposed adaptation approach is not confined to the embedding of generic GUI components into a three-tier architecture, but can be applied in a much wider context. A good example are the services on the application layer. Wrapping such large, business-oriented components in this way, however, almost certainly requires additional structuring and management techniques for the wrapper and adaptor code.

References [ATL]

Atlas, Architectures methodologies and Tools for computer integrated large scale engineering, Esprit project 7280, .

[BMR+ 96] F. Buschmann, R. Meunier, H. Rohnert, P. Sommerlad, and M. Stal. Pattern-Oriented Software Architecture – A System of Patterns. Wiley & Sons, 1996. [BRS98]

Klaus Bergner, Andreas Rausch, and Marc Sihling. A Component-Oriented Architecture for the CASE-Tool AutoFocus. In Roger Lee,

editor, Software Engineering : Proceedings of the IASTED Conference ‘98. ACTA Press, Anaheim, 1998. [BRSV98a] Klaus Bergner, Andreas Rausch, Marc Sihling, and Alexander Vilbig. A componentware development methodology based on process patterns. In PLOP‘98 Proceedings of the 5th Annual Conference on the Pattern Languaes of Programs. Robert Allerton Park and Conference Center, 1998. [BRSV98b] Klaus Bergner, Andreas Rausch, Marc Sihling, and Alexander Vilbig. An integrated view on componentware - concepts, description techniques, and development process. In Roger Lee, editor, Software Engineering : Proceedings of the IASTED Conference ‘98. ACTA Press, Anaheim, 1998. [Den91]

E. Denert. Software Engineering. SpringerVerlag, 1991.

[GHJV95]

E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.

[Jav98]

JavaSoft. Java Foundation Classes website, pro¯ ducts/¯ jfc/, com/¯ sun.¯ http:¯ //¯ java.¯ 1998.

[Mic96]

Microsoft Corporation, Redmont, WA (USA). Visual C++ 4.0 and Microsoft Foundation Class Library Manuals, 1996.

[OMG99]

OMG. OMG Unified Modeling Language Specification. Version 1.3, Object Management Group, 1999.

[Ste97]

Jeff Stephens. Virtual enterprises using groupware tools and distributed architectures. Public annual report, Vega Esprit Project 20408, 01/15/97.