l the services that OLE provides as well as offering additional functions, it presents a supers
et of OLE.
An OpenDoc part can be contained in or linked to an OLE container, and an OpenDoc container can contain or be linked to an OLE server application. This interoperability applies on every platform where both technologies exist, including OS/2 and Windows. The Windows version of OpenDoc was not generally available at this writing, and the design outlined here may change somewhat before the code ships later this year.
With both OS/2 and Windows, OpenDoc provides wrapper components that intercept and reroute method calls between containers and their embedded components (see the figure
"OpenDoc Parts as OLE Servers"
). Scripting is supported by mapping OLE Automation to OpenDoc's Open Scripting Architecture implementation and providing extensions where direct mappings are inappropriate.
There are differences between the OS/2 and Windows implementations of OpenDoc. The OS/2 code contains additional functions that manage the communication between Op
enDoc for Windows (Win-OS/2) and OS/2 and resolve platform differences. For example, interoperability calls on the Win-OS/2 implementation are replaced in OS/2 with Distributed System Object Model (DSOM) calls to OpenDoc for OS/2.
Registration and Run Time
OLE objects embedded in an OpenDoc container don't have to be explicitly registered with the OpenDoc shell; developers need only register their objects with OLE as they would normally. When an OLE object is detected, OpenDoc is informed via the OLE object's component wrapper (which is discussed in detail below). This wrapper queries the OLE registry to obtain the OLE-server executable name corresponding to the appropriate OLE class ID.
Although OpenDoc parts developers don't need to write additional code to take advantage of OLE interoperability, they must register their OpenDoc parts with OLE. The registration process is managed by the ODRegisterClass API.
Required parameters for ODRegisterClass include a vali
d class ID value, which can be obtained either by invoking the utility UIDGEN.EXE or by contacting Microsoft; a human-readable part name; and icon information. The API adds the parameter information to a file that OpenDoc then accesses to identify the DLL associated with the part at run time.
ODRegisterClass also creates a temporary OLE registration file, which is merged into the OLE registration database via REGEDIT.EXE. As a result, OLE is able to recognize new data types associated with the OpenDoc document shell. This somewhat cumbersome process is likely to be streamlined prior to general availability of the OpenDoc for Windows implementation in the third quarter of this year.
Two wrapper components represent the bulk of the interoperability function.
OLEPart
enables OLE components to be embedded in OpenDoc documents, while OLEWrapper enables OpenDoc components to be embedded in any OLE container.
OLEPart is used to wrap an OpenDoc container so that it behaves li
ke an OLE container; that is, it appears to OLE as a rectangular container that provides a single client site for any OLE object. OLEPart provides mappings for various OLE interfaces, such as IOleInPlaceFrame and IOleInPlaceUIWindow. OLE Control (OCX) interface support is also provided.
OLEWrapper is used to wrap OpenDoc parts so they appear as OLE servers. This is done by mapping all the interfaces that a well-behaved OLE server must implement to equivalent functions in the OpenDoc environment. In the current implementation, the OpenDoc document shell is executed once for every OpenDoc part embedded in an OLE container. This approach might be modified before the code is made generally available; while it provides crash protection between components, the performance of this design is slower than implementing a reentrant document shell.
OLEWrapper manages window creation and storage, menu and tool-space merging, and event notification between OLE and OpenDoc. OLEWrapper also provides IDropTarget
and IDragSource interfaces for drag-and-drop support.
Interoperability Design Model
Several additional areas define interoperability between OLE and OpenDoc. These include data persistence, drag and drop, and linking.
Components access persistent storage through their native services; that is, method calls on storage objects are not intercepted by component wrappers. Thus, a container document defines a single persistent storage file, depending on whether it's an OpenDoc or OLE container. Within this single file reside all the container document's embedded components, each in turn stored in the storage-file type appropriate for that component.
For example, when an OLE server is saved as part of an OpenDoc container, the embedded OLE objects are saved as DocFiles, which are then included in their entirety in the OpenDoc container's persistent Bento document file. Likewise, an OpenDoc part typically saves its content in a storage unit in a Bento file. Embedded in a
n OLE container, the OpenDoc part still saves in a Bento format, but the Bento storage unit is in the embedding OLE container's DocFile.
Drag-and-drop interoperability permits OLE objects to be dragged and dropped into OpenDoc containers and vice versa. Drag and drop for OLE-wrapped OpenDoc objects maps the XMPDragDrop class in OpenDoc to the IDropSource object in Windows.
OLE and OpenDoc components can be linked together, with both sets able to act as target and source. To implement this, all link specifications in OpenDoc are managed by composite OLE monikers. This ensures unique monikers for each document as well as each contained component within a document.
Good-Bye, OLE?
Code an OpenDoc part in OS/2 or Windows or on the Mac, and you have an OpenDoc part and an OLE component with no extra development effort or cost. So, if OpenDoc interoperates with OLE, why switch from OLE to OpenDoc?
The answer is twofold. First, OpenDoc/OLE interoperability is availab
le only on those platforms where both OpenDoc and OLE exist. There are more platforms slated to support OpenDoc alone in the near future than there are platforms slated to support both technologies. Developers who write software for OpenDoc will be able to take advantage of all supported platforms.
Second, the learning curve for developers must be considered. Since both architectures interoperate, developers may choose one over the other based partially on how easily they can get their products to market. The number of APIs that must be implemented to develop a basic OpenDoc component is substantially less than the number required to develop a similar OLE component. As OpenDoc tools emerge, developers should find it even easier to develop cross-platform OpenDoc components.
Basically, OpenDoc developers get something for nothing--well, almost nothing. Running nonnative software under an abstraction layer, such as OLEPart/OLEWrapper, always exacts some degree of performance penalty.
As with
any new technology, leading-edge developers will have a steeper learning curve than those who enter the market-adoption phase after tools such as visual compilers and builders, wizards, and cross-platform tools become available. That's a price some developers are already paying to be among the first to exploit the power of OpenDoc in their commercial offerings.
Acknowledgments
Stew Nickolas and Mark Rogalski provided technical details for this article. Stew is a senior programmer on the IBM OpenDoc team; Mark is the team lead for OpenDoc/OLE interoperability and the technical lead for Win-OS/2.
Info on the WWW
Apple:
http://www.opendoc.apple.com
CI Labs:
http://www.cilabs.org/
IBM:
http://www.software.ibm.com/clubopendoc/index.html