Copyright © 1997 AIIM International
HTML EDITION 2.0-3 Review Draft last updated 2001-09-04-12:49 -0700 (pdt)
For the latest information on ODMA and the ODMA Specifications, consult the ODMA section of the AIIM DMware Development Site. Current locations of development sites can be found through AIIM DMware. The current status of ODMA and its support, including current status of ODMA 2.0, is reported in the ODMA Support section.
Specification History
1.1 Document IDs
1.2 Constants
1.3 Error Handling
1.4 Connections and the ODMA Connection Manager
1.5 Document Format Names
1.6 DMS or Native File System Dialogs - Which to Display First
1.7 Character Sets
1.8 Application Interfaces
1.9 Query Syntax
1.10 Query Examples
2.1
ODMActivate
2.2ODMCloseDoc
2.3ODMCloseDocEx
2.4ODMGetAlternateContent
2.5ODMGetDMS
2.6ODMGetDMSCount
2.7ODMGetDMSInfo
2.8ODMGetDMSList
2.9ODMGetDocInfo
2.10ODMGetDocRelation
2.11ODMGetLeadMoniker
2.12ODMNewDoc
2.13ODMOpenDoc
2.14ODMQueryCapability
2.15ODMQueryClose
2.16ODMQueryExecute
2.17ODMQueryGetResults
2.18ODMQueryInterface
2.19ODMRegisterApp
2.20ODMSaveAs
2.21ODMSaveAsEx
2.22ODMSaveDoc
2.23ODMSaveDocEx
2.24ODMSelectDoc
2.25ODMSelectDocEx
2.26ODMSetAlternateContent
2.27ODMSetDMS
2.28ODMSetDocEvent
2.29ODMSetDocInfo
2.30ODMSetDocRelation
2.31ODMUnRegisterApp
3.1
ODMGetODMInterface
3.2IODMDocMan
Interface
3.3IODMQuery
Interface
3.4IODMDocMan2
Interface
ODM_E_INUSE
as a valid return code in ODMActivate
.ODMQuery*
functions and
the IODMQuery
COM interface. Also added a clarification to the expected
behavior of an application when calling ODMSaveAs
and an empty string is
returned for lpszNewDocId
. IODMDocMan2
interface. Defined several items to help provide better
out-of-the-box integration between desktop applications and DMS. Also added
clarifications to the existing specification and arranged the functions
alphabetically.The original impetus for the Open Document Management API (ODMA) was the recognition that there was no standard method for a client application to integrate with a Document Management System (DMS). Each DMS vendor wrote separate integration code for each of the major client applications they supported. Applications that did not have integrations written for them by the DMS vendors would have to write and support a separate integration for each DMS that was supported. This required a complete matrix of integrations, each with its own set of bugs, limitations and reliability issues. It seemed obvious that a high level standard for connecting applications and document management systems was a natural fit.
A small group of application and DMS vendors started working together to create an API that would allow applications and document management systems to inter-operate through a single high level API. This implied the creation of a standard, however, the creation of a standard has many pitfalls. Probably the biggest problem is that a lot of work can be put into the creation of the standard, and nobody uses it.
The industry is filled with examples of standards that were obsolete by the time they made it through the standardization process. By the time some standards make it through the standardization process, they are so large and unwieldy they are almost impossible to implement and maintain. Company politics and hidden agendas of the participants can play as big a role in the adoption of a standard as trying to solve the problem in the first place. The industry is also full of proprietary API’s that claim to be standards, but are not. The initial group of vendors that met and formed the ODMA consortium wanted to avoid as many of these problems as possible.
The working rules of the ODMA consortium are fairly simple.
It is difficult to express the importance the initial members of the consortium placed on wanting to create a useful API that is vendor and platform independent while still simple to implement. They recognized that they could solve 80 percent of the problem easily and were willing to live with having to solve another 10 percent over time and probably never being able to solve the final 10 percent.
The Open Document Management API (ODMA) is a standardized, high-level interface between desktop applications and document management systems (DMSs). Its purposes are:
ODMA specifies a set of interfaces that applications can use to initiate actions within a DMS. The API is intended to be relatively easy for application vendors to incorporate into updates of existing applications. It should not require major restructuring of an application to integrate it with ODMA. Note that this version of ODMA does not specify how DMSs may initiate actions within the applications.
The ODMA API is platform-independent. The associated data type definitions and binding information are platform-specific. Currently, most of the work has been done in Windows. It makes this document look Windows specific, but over time, the platform specific entries for other platforms will be added as they are defined.
Many of the ODMA functions accept or return a Document ID parameter. A document ID is a persistent, portable identifier for a document. It can be stored and used in a later session, and it can be passed across platforms via email or other processes.
A Document ID is a case insensitive, null-terminated string of printable characters. Although a document ID is case insensitive, an application should never change the case of a document ID. The format of a document ID is
::ODMA\DMS_ID\DM_SPECIFIC_INFO
The DMS_ID
portion of a document ID will identify which DMS provided the
ID. This information is primarily for the use of ODMA itself; applications
using ODMA should not need to know which DMS provided a particular ID. The
ODMA group members will coordinate these IDs to ensure their uniqueness. The
maximum length of the DMS_ID
portion of the document ID is specified by the
constant ODM_DMSID_MAX
. The DM_SPECIFIC_INFO
portion of the ID will
vary depending on which DMS built the ID. The total length of the document ID
including the terminating Null character cannot exceed ODM_DOCID_MAX
bytes.
ODMA-aware applications should be able to handle a document ID anywhere they handle an externally-generated document filename. For example, if the application allows a document filename to be passed as a command line argument then it should allow a document ID to be passed in the same way. If the application allows document filenames to be used in DDE commands then it should also support the use of document IDs in the same commands.
Although the technical definition of a document ID is a case insensitive,
null-terminated strings of printable characters, there are some general rules
that are more likely to make a DMS and ODMA application work better together.
ODMA was designed so that it would be easy to add to an application without
major modifications in code or structure. If a DMS passes a document ID that
breaks fundamental rules of normal file and path names it will probably run
into problems if it is passed in on a command line. Special characters like ^
,
[
, ]
, |
, *
, -
,
>
, <
and ?
are processed by the UNIX shell even before
they are seen by the application. It is possible to pass these characters by
using special escape sequences, but that places a burden on the DMS vendor to
process the document ID before giving it to the ODMA application. Some
operating systems require the application to handle the reverse process of
interpreting and removing the escape characters. The application may be able
to support the escape removal on the command line, but not if the document ID
with escape characters is returned in a procedure call. In most cases, it is
easier to generate a document ID that contains a fairly simple set of
characters. The following table suggests characters it may be wise to avoid
for different platforms.
Platform | Characters to avoid |
Windows 3.x | " ‘ < > * ? | and the space
character |
Windows 95 | " ‘ < > * ? | |
Other platforms to be defined |
The following table lists the constants that are defined in the odma.h
header.
CONSTANTS | Win 3.x | Win32 | Mac | UNIX | Other |
ODM_DOCID_MAX Maximum length of a document ID including the null-terminator. |
80 | 255 | 255 | 255 | 255 |
ODM_FILENAME_MAX Maximum length of a path/filename returned by ODMA including the terminating Null character. |
128 | 255 | 255 | 1024 | 255 |
ODM_API_VERSION The version of the ODMA API to which this header file corresponds. See ODMRegisterApp . |
200 | 200 | 200 | 200 | 200 |
ODM_DMSID_MAX Maximum length of a DMS ID including the null-terminator. |
9 | 9 | 9 | 9 | 9 |
ODM_APPID_MAX Maximum length of an Application ID including the null-terminator. |
16 | 16 | 16 | 16 | 16 |
ODM_FORMAT_MAX Maximum length of a content format string including the null-terminator. |
81 | 81 | 81 | 81 | 81 |
ODM_QUERYID_MAX Maximum length of a query ID string including the null-terminator. |
255 | 255 | 255 | 255 | 255 |
Nearly all of the ODMA functions use the return value to indicate to the
calling application whether the function succeeded, failed because the user
canceled the operation, or failed for other reasons. The DMS is responsible
for displaying informational error messages to the user where appropriate
except when the ODM_SILENT
flag is specified. The DMS must take care to
return the appropriate error indication because applications may act
differently depending on whether an ODMA call was canceled by the user or
failed for other reasons. The calling application generally should not display
error messages when an error value is returned from ODMA unless the ODM_SILENT
flag was specified.
The ODMA connection manager is a small software module that sits between applications using ODMA and document management systems implementing ODMA. It manages the connections between these components and routes ODMA calls to the appropriate provider. A freely redistributable copy of the ODMA connection manager will be provided to any vendor wishing to implement or make use of the ODMA API. This is a place where it would be possible to provide mapping code that would allow ODMA to have truly platform independent document IDs, however, it currently only manages connections and does not touch document IDs.
When new documents are registered with a DMS via ODMA and when an existing
document's format is changed by an application, the application passes a
document format name to ODMA. Document format names are null-terminated
strings defining the format of a document's content. These strings have a
maximum length defined by the ODM_FORMAT_MAX
constant.
There are several places in ODMA where a content format name for a document
can be specified or requested. The ODMNewDoc
,
ODMSaveAs
and ODMSaveAsEx
functions each have a
lpszFormat
parameter where a format
can be specified. The ODMSaveAs
also has a callback, which uses a
format string. The ODM_CONTENTFORMAT
attribute can be requested or set
using the ODMGetDocInfo
and ODMSetDocInfo
functions.
The ODMA 1.0 specification did not attempt to standardize the format names used by DMS and application vendors. This was a significant limitation in some cases. The DMS would not know in advance what type of file was being created by the application. Also an application that saved an existing file back to the DMS using a different format would have no standard format name to give to the DMS. This model relied on both the DMS and the application being able to auto-detect all file formats.
ODMA 2.0 defines guidelines to standardize format names. This has become
necessary due to vendors’ desire to have applications and DMSs more tightly
integrated and because ODMA 2.0 introduces some new functions which require
standardization in order to work. The new ODMGetAlternateContent
and
ODMSetAlternateContent
functions require the DMS and application to
have a standard way to identify file content. A new document attribute called ODM_ALTERNATE_RENDERINGS
allows an application to find out if a DMS can
provide a document in other formats and make a choice of which to use.
ODMA has defined the following guidelines to standardize how a DMS or application might specify a document’s content format:
application/msword
.doc
.doc/MS Word 95 Document
.doc/MS Word 97 Document
image/tiff
.TIF
.TIFF
.TIF/Tagged Image File Format
.TIF/Scanned TIFF
A DMS or application can use the Windows Registry or its own mapping capability to convert a file extension to a MIME code or vice versa. Note that some file extensions are used by more than one application, some file types have multiple valid file extensions, and that some MIME content types are used to define more than one file type within the same application. A DMS or application may have use whatever format name is most precise.
ODMA imposes no rules on applications requiring them to always show the DMS dialogs first in response to filing commands such as File Open and File Save As. ODMA applications are encouraged to provide a user preference setting so the user can designate if the application’s native file system dialog or the DMS’s dialog is displayed first. Ideally the application may provide a push-button or some other control in its native file system dialog box to allow the user to quickly select the DMS dialog box.
If the application cannot provide one or more of the options described
above then they have no choice but to always display the DMS dialog box in
response to the File Open and File Save As commands. Each ODMA compliant DMS
must provide a way for the user to select the native file system from dialogs
displayed while processing the ODMSelectDoc
,
ODMSelectDocEx
, ODMNewDoc
,
ODMSaveAs
and
ODMSaveAsEx
functions. The DMS
returns the ODM_E_APPSELECT
status if the user elects to use the native
file system. When this status is returned the application can display their
dialog box. If the user wishes to return to the DMS dialog box they will have
to cancel and re-do the file command.
All strings passed to or
returned from ODMA functions should be null-terminated series of octets, in
the standard character set of the system on where ODMA is being used. So for
example, 8859-1 would be used on English Windows, Shift-JIS would be used on
Japanese Windows, etc. The term "null-terminated" as used in this
specification means terminated by the character set's natural Null character.
For most character sets this means a single byte with the value 0x0
.
If an application obtains an ODMA document ID on one platform and later uses it on another platform, the application is responsible for translating the ID to the character set being used on the second platform before using it there.
An
ODMA-aware application can choose to communicate with the ODMA Connection
Manager either through a traditional, function-oriented API or through
Component Object Model (COM) interfaces. Prototypes and constants used for the
function-oriented API are included in the odma.h
header file. Prototypes,
constants, and interface definitions for the COM interface are included in the
odmacom.h
header file.
After calling ODMRegisterApp
, applications can obtain one or more
COM interfaces to ODMA through the ODMQueryInterface
function. The
IODMDocMan
interface provides an alternate entry point to most of the
ODMA functions documented below. Other functions are defined in the IODMDocMan2
and
IODMQuery
interfaces. These interfaces and their
interface IDs are defined in the odmacom.h
header file.
Note that IODMDocMan::QueryInterface
will only query the default DMS
for the calling application. The application must call ODMQueryInterface
in
order to query other DMSs.
The query syntax described
here is used in the ODMQueryExecute
function.
<query> | :: select <returned_list> <search_criteria> |
<returned_list> | :: <returned_item> [, <returned_list>] |
<returned_item> | :: ODM_DOCID :: ODM_NAME |
<search_criteria> | :: <search_clause> :: <where_clause> :: <search_clause> <where_clause> :: <where_clause> <search_clause> |
<search_clause> | :: search document contains <expression> |
<expressioin> | :: ( <expression>) :: [ not ]
( <expression>) :: <term> [<operator> <expression>] |
<term> | :: ‘ <word>’ :: [ not ] ‘ <word>’ |
<operator> | :: and :: or |
<word> | is a user supplied word. If there is a single quote (’ ) inside this
word, it needs to be represented with two consecutive single quotes
(’’ ). |
<where_clause> | :: where <condition_list> |
<condition_list> | :: <condition> [<operator> <condition_list>] |
<condition> | :: <attribute> <op> |
‘ <attribute_value>’ <attribute> |
:: ODM_FORMAT :: ODM_NAME :: ODM_AUTHOR :: ODM_TYPE ::
ODM_DMS_DEFINED: <dms_attribute> :: * Any other document attribute listed in Appendix A |
<op> | :: = :: != :: <> :: > :: < :: <= ::
>= |
<dms_attribute> | is a DMS specific attribute name. |
<attribute_value> | is a user supplied value for ODM_NAME , etc. If there is a single
quote (’ ) inside any of these names, it must be represented with two
consecutive single quotes (’’ ). |
Example 1: | select ODM_DOCID, ODM_NAME |
Example 2: | select ODM_DOCID, ODM_NAME |
Example 3: | select ODM_DOCID, ODM_NAME |
Example 4: | select ODM_DOCID, ODM_NAME |
The following section describes each function in the ODMA API that a typical application would use. The functions are listed in alphabetical order.
ODMSTATUS ODMActivate( ODMHANDLE handle, WORD action, LPSTR lpszDocId)
This function causes the DMS to perform actions that do not require cooperation from the calling application. Control is returned to the calling application after the specified action has been completed, except where noted. A DMS is not required to support all of these actions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMCloseDoc( ODMHANDLE handle, LPSTR lpszDocId, DWORD active Time, DWORD pagesPrinted, LPVOID sessionData, WORD dataLen)
An application that has opened a document by calling ODMOpenDoc
must call
ODMCloseDoc
when it is finished using the document. The application
should not call this function until after it has closed the document, because
the DMS may move the document or make it inaccessible as a result of this
call. Note that this function will not cause the document to be saved into the
DMS's persistent repository unless ODMSaveDoc
has been called
previously.
It is possible for a user to explicitly check-out/reserve a document using
either ODMActivate
or a command provided by the DMS. If a document was
already reserved by the user before ODMOpenDoc
was called, then when
ODMCloseDoc
is called it is recommended that the DMS keep the document
reserved. The DMS should only check-in/unreserve the document in ODMCloseDoc
if it first displays a dialog box confirming this with the
user.
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMCloseDocEx( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags, DWORD activeTime, DWORD pagesPrinted, LPVOID sessionData, WORD dataLen)
ODMCloseDocEx
is the same as ODMCloseDoc
except it has a
pwdFlags
parameter. There is an ODM_SILENT
flag to facilitate
unattended document processing. Some DMSs display a user interface when
closing a document. This flag allows the calling application to suppress this
UI.
An application that has opened a document by calling ODMOpenDoc
must
call ODMCloseDoc
or ODMCloseDocEx
when it is finished using the
document. The application should not call this function until after it has
closed the document, because the DMS may move the document or make it
inaccessible as a result of this call. Note that this function will not cause
the document to be saved into the DMS's persistent repository unless ODMSaveDoc
or
ODMSaveDocEx
has been called previously.
It is possible for a user to explicitly check-out/reserve a document using
either ODMActivate
or a command provided by the DMS. If a document was
already reserved by the user before ODMOpenDoc
was called, then when
ODMCloseDocEx
is called it is recommended that the DMS keep the
document reserved. The DMS should only check-in/unreserve the document in ODMCloseDocEx
if the
ODM_SILENT
flag is not set and it first
displays a dialog box confirming this with the user.
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMGetAlternateContent ( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation)
This function causes the DMS to return an alternate content file for the
specified document. The format of the alternate content file should be one of
the formats returned by the ODM_ALTERNATE_RENDERINGS
item in a previous
call to ODMGetDocInfo
. The application is responsible for deleting the
alternate content file when it is finished using it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function provides an application a programmatic way to get its default
DMS. The DMS ID of the current DMS for the application will be returned. This
can be either the default DMS from the registry or a DMS previously set by the
application using ODMSetDMS
.
|
|
|
|
|
WORD ODMGetDMSCount( )
This is an informational function. It will count the number of DMSs
currently registered on the system. This information can be used to determine
the minimum size for the buffer in a call to ODMGetDMSList
.
none.
The number of DMSs currently registered on the system.
ODMSTATUS ODMGetDMSInfo( ODMHANDLE handle, LPSTR lpszDmsId, LPWORD pwVerNo, LPDWORD pdwExtensions )
This function returns information to the application about the currently active DMS. The application if free to only request the information it needs.
|
|
|
|
|
|
WORD ODMGetDMSList( LPSTR buffer, WORD buffer_size )
This function gets a list of the DMSs currently registered on the system.
|
The number of DMSs returned in buffer.
ODMSTATUS ODMGetDocInfo( ODMHANDLE handle, LPSTR lpszDocId, WORD item, LPSTR lpszData, WORD dataLen )
An application can use this function to obtain information about a document from the DMS. It is recommended that the DMS not display any user interface while processing this function.
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMGetDocRelation( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, LPSTR lpszPreviousId )
An application can use this function to retrieve pointers to document versions linked to a particular document ID. This function would be used typically as part of retrieving a compound document. It could also be used when saving an updated component document, for the user to verify which compound documents will be impacted by any changes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMGetLeadMoniker( ODMHANDLE handle, LPSTR lpszDocId, LPMONIKER FAR *ppMoniker )
Applications that are OLE 2 servers typically form composite monikers for their OLE links by combining a file moniker representing the document with one or more item monikers representing a particular section of the document. This approach often does not work in environments where Document Management Systems are in use because the filename that the application sees is usually just temporary. This function lets the application obtain a leading moniker from the DMS that can be used in place of the file moniker.
This function will only be available on platforms supporting OLE 2. This
function may not be supported by some DMSs; those DMSs will return ODM_E_FAIL
. In this case the application should go ahead and use the
file moniker as though ODMA were not present. Note that this function is
prototyped in odmacom.h
instead of odma.h
, so that non-OLE-aware applications
do not have to #include
the OLE header files.
|
|
|
|
|
|
|
ODMSTATUS ODMNewDoc( ODMHANDLE handle, LPSTR lpszDocId, DWORD dwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation )
This function causes the DMS to create a new document profile and return the document ID for the new document to the calling application. The DMS may create a temporary or pending document profile; it may not have actually created a document in its data store. If the DMS displays a dialog box for this function it should be task/application modal.
The document ID returned by the DMS in ODMNewDoc
provides a document
context for the application. This document ID must be used in subsequent ODMA
function calls which are needed to complete the process of saving a new
document into a DMS. If the user decides to cancel the operation or save the
document to the native file system, then the application should call ODMCloseDoc
or
ODMCloseDocEx
and throw the document ID away. The
document ID returned by ODMNewDoc
may be temporary so the application must be
prepared for the possibility that the DMS will later override it in a call to ODMSaveAs
,
ODMSaveAsEx
or ODMSaveDoc
or
ODMSaveDocEx
.
The calling sequence for creating a new
document, which isn’t based on
another existing document, is as follows: ODMNewDoc
,
ODMSaveAs
, ODMOpenDoc
then
ODMSaveDoc
. Finally the document must be
closed with ODMCloseDoc
. The above sequence will likely involve user
interaction with the DMS displaying one or more dialog boxes.
It is possible for an application to create a new document without any user
interaction if the DMS supports it. To accomplish this the calling application
should set the ODM_SILENT
flag and use the following call sequence:
ODMNewDoc
, {ODMSetDocInfo
},
ODMSaveAsEx
, ODMOpenDoc
,
ODMSaveDocEx
and ODMCloseDocEx
.
Optionally, if the application wishes to pre-set some document attributes
in the Save As dialog box it can call ODMSetDocInfo
using the
document
ID from ODMNewDoc
. This should be done before calling
ODMSaveAs
or ODMSaveAsEx
. Example attributes the DMS might accept and perhaps
show in its Save As dialog are ODM_NAME
,
ODM_AUTHOR
, ODM_KEYWORDS
and others. After
ODMSaveAs
is called, the
application might wish to call ODMGetDocInfo
to see if the user changed
the value of any document attribute it is tracking.
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMOpenDoc( ODMHANDLE handle, DWORD flags, LPSTR lpszDocId, LPSTR lpszDocLocation )
This function causes the DMS to make a document available to the application. It performs any necessary pre-processing (mapping network drives, checking security, etc.) and then returns to the application a temporary filename that can be used to access the document during the current session. Note that this function does not open the document file; it merely makes the file temporarily available to the calling application. The application can then open, read, write and close the file as needed.
If ODM_MODIFYMODE
is requested, the DMS may refuse the request if
the user has view-only rights (ODM_E_ACCESS
) or if the document is
currently checked-out (ODM_E_INUSE
) to another user. It is
recommended that the application retry the request specifying ODM_VIEWMODE
in
both cases so that the user can at least view the document and possibly save
changes to a new document.
Applications are encouraged to give the user the same level of feedback if a DMS based document is opened for read-only access as they would for a document based in the platform’s native file system.
When the application is finished using a file which was opened with either ODM_MODIFYMODE
or
ODM_VIEWMODE
it must call ODMCloseDoc
or ODMCloseDocEx
. When an application is finished using a file that
was obtained with the ODM_REFCOPY
option it does not have to call
ODMCloseDoc
or
ODMCloseDocEx
, however, it must delete the
temporary file.
If an application has opened a document in ODM_VIEWMODE
and wishes
to switch to ODM_MODIFYMODE
, it must first call ODMCloseDoc
or
ODMCloseDocEx
then call
ODMOpenDoc
requesting ODM_MODIFYMODE
. The same is true if the application wishes to switch
from ODM_MODIFYMODE
to ODM_VIEWMODE
. The
ODM_E_ALREADYOPENED
error status is returned by the DMS if the
application attempts to re-open a document that it has already opened in
either of these two modes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If the application attempts to open a document for ODM_VIEWMODE
that
it already has opened for ODM_VIEWMODE
, then the DMS may either return
the ODM_E_ALREADYOPNED
error status or
ODM_SUCCESS
along with
the previously returned temporary file specification. The DMS should not
return ODM_SUCCESS
in this case unless it is maintaining a reference
count of the number of times this application has opened the document for ODM_VIEWMODE
access. The application must call
ODMCloseDoc
or ODMCloseDocEx
once for every time the document was successfully opened.
On the last close call the DMS will delete the temporary file.
ODMSTATUS ODMQueryCapability( ODMHANDLE handle, LPCSTR lpszDmsId, DWORD function, DWORD item, DWORD flags );
This function is used by a client application to determine if a DMS
supports a given ODMA function, or a specific action
code in
ODMActivate
or a
specific event code in ODMSetDocEvent
. It can also be used to determine if
the DMS supports getting or setting a given document attribute using
ODMGetDocInfo
or ODMSetDocInfo
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function is used by a client application to indicate that it has finished using the query and that the involved DMS(s) should release any resources and/or memory for the result set.
|
|
|
|
|
ODMSTATUS ODMQueryExecute( ODMHANDLE handle, LPCSTR lpszQuery, DWORD flags, LPCSTR lpszDMSList, LPSTR queryId )
This function will pass the lpszQuery
along to each DMS as specified by the
flags
parameter. It will return a query ID that can be used in subsequent
calls to ODMQueryGetResults
and
ODMQueryClose
. If this function is
successful, the calling application must eventually call ODMQueryClose
to
release this query.
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMQueryGetResults( ODMHANDLE handle, LPCSTR queryId, LPSTR lpszDocId, LPSTR lpszDocName, WORD docNameLen, LPWORD pwDocCount )
This function will fetch pwDocCount
number of documents at a time.
|
|
|
|
|
|
|
|
|
|
|
HRESULT ODMQueryInterface( ODMHANDLE handle, LPSTR lpszDocId, REFIID riid, LPVOID FAR *ppvObj )
An application can use this function to get a COM interface from an ODMA
provider. All ODMA providers support the IODMDocMan
interface and some support
IODMDocMan2
and IODMQuery
. Individual DMSs may support other interfaces as
well. Note that this function is prototyped in odmacom.h
instead of
odma.h
, so
that non-COM-aware applications do not have to #include
the header files that
define interface IDs.
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMRegisterApp( ODMHANDLE FAR *pHandle, WORD version, LPSTR lpszAppId, DWORD dwEnvData, LPVOID pReserved )
ODMRegisterApp
registers an application with the appropriate Document
Management System (DMS) and returns a session handle that can be used in calls
to other ODMA functions.
An application normally calls this function before calling any other ODMA
function. Some functions such as ODMGetDMSCount
,
ODMGetDMSList
, ODMGetDMS
and ODMSetDMS
can be called before
ODMRegisterApp
. These are used by
applications that wish to control which DMS they will access when
ODMRegisterApp
is called.
A task may call ODMRegisterApp
more than once. Each call will return a
different handle, each of which must be released with ODMUnRegisterApp
.
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSaveAs( ODMHANDLE handle, LPSTR lpszDocId, LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, LPVOID pInstanceData )
This function causes the DMS to return a new document ID for a document
that is based on an existing document. An application would typically call
this function in response to the user selecting a File Save As menu option.
ODMSaveAs
causes the DMS to display options to the user for selecting the
destination for the new document. This might be an entirely new document or a
new version of the current document. Any dialog box displayed by the DMS
should be task/application modal.
Often the application will want to present additional options to the user
at this point such as different file formats or encrypting the document. This
is accomplished via the pcbCallBack
parameter. ODMA implementers should
provide a method for users to access this function if desired. For example,
the DMS may show a dialog that includes an Options button. If the user clicks
this button, the DMS would call the application's callback function which
would give the application a chance to display other save options.
Note that following a successful call to ODMSaveAs
the calling application
may have two different document IDs to work with. This is different than the
situation with ODMSaveDoc
where the new ID replaces the old one in the current
session. The state of the document specified by the old ID remains the same
after the call. The document specified by the new ID will be in the closed
state following the call. A typical sequence of operations an application
might follow in response to the user selecting File | Save As would be:
ODMSaveAs
. If an
empty string is returned for the new ID, then the application should call
ODMSaveDoc
with the current document ID to indicate to the DMS that document
should be saved in the document repository. If a new ID for the document is
returned then continue with the steps below.
ODMOpenDoc
on
the new ID. This returns a new filename
for the document.
ODMSaveDoc
on the new ID to indicate to the DMS that the new document should
be saved in the document repository.
ODMCloseDoc
on the
old ID.
ODMCloseDoc
on the
new ID.
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
|
|
|
|
|
|
ODMSTATUS ODMSaveAsEx( ODMHANDLE handle, LPSTR lpszDocId, LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, LPVOID pInstanceData, LPDWORD pdwFlags )
The ODMSaveAsEx
function extends ODMSaveAs
by adding a
pdwFlags
parameter
to allow for unattended document creation. It also can be called without first
calling ODMNewDoc
.
This function causes the DMS to return a new document ID for a document
that is based on an existing document. An application would typically call
this function in response to the user selecting a File Save As menu option.
ODMSaveAsEx
causes the DMS to display options to the user for selecting the
destination for the new document. This might be an entirely new document or a
new version of the current document. Any dialog box displayed by the DMS
should be task/application modal.
Often the application will want to present additional options to the user
at this point such as different file formats or encrypting the document. This
is accomplished via the pcbCallBack
parameter. ODMA implementers should
provide a method for users to access this function if desired. For example,
the DMS may show a dialog that includes an Options button. If the user clicks
this button, the DMS would call the application's callback function which
would give the application a chance to display other save options.
Note that following a successful call to ODMSaveAsEx
the calling
application may have two different document IDs to work with. This is
different than the situation with ODMSaveDoc
or
ODMSaveDocEx
where the new ID
replaces the old one in the current session. The state of the document
specified by the old ID remains the same after the call. The document
specified by the new ID will be in the closed state following the call. A
typical sequence of operations an application might follow in response to the
user selecting File | Save As would be:
ODMSaveAsEx
. If
an empty string is returned for the new ID, then the application should call
ODMSaveDoc
or ODMSaveDocEx
with the current document ID to indicate to the
DMS that document should be saved in the document repository. If a new ID
for the document is returned then continue with the steps below.
ODMOpenDoc
on the new ID. This returns a
new filename
for the document.
ODMSaveDoc
or ODMSaveDocEx
on the new ID to indicate to the DMS that the new
document should be saved in the document repository.
ODMCloseDoc
or
ODMCloseDocEx
on the old ID.
ODMCloseDoc
or ODMCloseDocEx
on the new ID.
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSaveDoc( ODMHANDLE handle, LPSTR lpszDocId, LPSTR lpszNewDocId )
This function tells the DMS that the document should be saved to the
document repository. An application would typically call this function after
saving changes to the temporary file returned by
ODMOpenDoc
. A new document
ID is returned to the application which should be used for all subsequent
operations on the document. This ID replaces the previous document ID in the
current session. The new ID may or may not be the same as the
original ID. It
will usually be the same unless the DMS saved the document as a new version or
as a new document. If the new ID is different from the
previous ID then the
previous ID cannot be used subsequently without doing an ODMOpenDoc
on it.
|
|
|
|
|
|
|
|
ODMSTATUS ODMSaveDocEx( ODMHANDLE handle, LPSTR lpszDocId, LPSTR lpszNewDocId, LPDWORD pdwFlags )
This function tells the DMS that the document should be saved to the
document repository. ODMSaveDocEx
is basically the same as
ODMSaveDoc
, except
it has a pwdFlags
parameter. This provides the application with more control
during the document creation or save process. There is an ODM_SILENT
flag that
facilitates unattended document creation or saving. Some DMSs display a user
interface when saving a document (i.e. to have the user specify revision or
version information). This flag allows the calling application to suppress
this UI if necessary or to influence it, if the DMS should allow that.
An application would typically call this function after saving changes to
the temporary file returned by ODMOpenDoc
. A
new document ID is returned to
the application which should be used for all subsequent operations on the
document. This ID replaces the previous document ID in the current session.
The new ID may or may not be the same as the original ID. It will usually be
the same unless the DMS saved the document as a new version or as a new
document. If the new ID is different from the previous ID then the previous ID
cannot be used subsequently without doing an ODMOpenDoc
on it.
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSelectDoc( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags )
This function causes the DMS to return a document ID representing a document that has been selected for some action. Typically the DMS will display searching and other dialogs that allow the user to interactively select a document from among those managed by the DMS. An application would typically call this function whenever the user needs to select a document to be opened or imported. Any dialog box displayed by the DMS should be task/application modal.
If the user elects to open a document in ODM_VIEWMODE
, then the
application should open the document with ODMOpenDoc
specifying
ODM_VIEWMODE
.
If a user selects ODM_MODIFYMODE
, the application is free to
open the
document with either the ODM_VIEWMODE
or
ODM_REFCOPY
options if it only needs
read-only access to it.
|
|
|
|
|
|
|
|
|
|
|
In the case that ODM_E_APPSELECT
is returned and a document is opened
through the application's regular file selection facilities, the following
behaviors are recommended:
ODMSaveAs
function). This will allow documents to be imported into the DMS.
The exception to this is if the application allows the user to select a DMS
from within its native file system Save As dialog.
ODMSTATUS ODMSelectDocEx( ODMHANDLE handle, LPSTR lpszDocIds, LPWORD pwDocIdsLen, LPWORD pwDocCount, LPDWORD pdwFlags, LPSTR lpszFormatFilter )
ODMSelectDocEx
extends ODMSelectDoc
. This function causes the DMS to
return one or more document IDs representing documents that have been selected
for some action. An application may call this function if it allows the user
to open multiple documents in one command. Typically the DMS will display
searching and other dialogs that allow the user to interactively select
documents from among those managed by the DMS. If a DMS does not support
multiple selection, then it is free to limit the user to selecting only one
document. Any dialog box displayed by the DMS should be task/application
modal.
The ODMSelectDocEx
function has an
lpszFormatFilter
parameter which will
allow an application to specify to a DMS what file types the user should
select. This can provide for closer integration between the application and
the DMS.
If the user elects to open a document in ODM_VIEWMODE
, then the
application should open the document with ODMOpenDoc
specifying
ODM_VIEWMODE
.
If a user selects ODM_MODIFYMODE
, the application is free to
open the
document with either the ODM_VIEWMODE
or
ODM_REFCOPY
options if it only needs
read-only access to it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSetAlternateContent( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation )
This function allows an application to create or update an alternate
content file for the specified document in the DMS. The application can either
provide the alternate content file or it can instruct the DMS to create or
update the content file itself. The format of the alternate content file is
specified in the ODMSetAlternateContent
function call. The DMS may or may not
accept the specified alternate content file. The application is responsible
for deleting the alternate content file when it is finished using it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function provides an application a programmatic way to set its default
DMS. ODMSetDMS
does not change any default DMS settings in the registry. The
DMS ID
set using this function will take effect the next time the application
calls ODMRegisterApp
. It will not alter the default DMS in any existing
session the application has already established with ODMRegisterApp
.
|
|
|
|
|
ODMSTATUS ODMSetDocEvent( ODMHANDLE handle, LPSTR lpszDocId, DWORD flags, DWORD event, LPVOID lpData, DWORD dwDataLen, LPSTR lpszComment )
An application can use this function to pass event information about the document to the DMS. Events like printing, sending, posting can be sent by the application to the DMS. The DMS may or may not accept the event information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSetDocInfo( ODMHANDLE handle, LPSTR lpszDocId, WORD item, LPSTR lpszData )
An application can use this function to pass information about the document to the DMS. The DMS may or may not accept the information; most DMSs validate attributes like document types and authors against predefined tables.
It is recommended that the DMS not display any user interface while processing this function.
|
|
|
|
|
|
|
|
|
|
|
|
ODMSTATUS ODMSetDocRelation( ODMHANDLE handle, LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, LPSTR lpszPreviousId)
An application can use this function to maintain relationship and hierarchy information in the DMS about a compound document structure that it is manipulating external to the DMS. This function would typically be used as part of saving a new or updated version of the master document, or when the user requests the application to review and update the version that has been linked to.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ODMUnRegisterApp( ODMHANDLE handle )
An application that previously registered itself with a DMS via
ODMRegisterApp
should call this function when it is finished using the DMS.
This would typically be done when the application is shutting down. After this
call returns, the DMS session handle is no longer valid and cannot be used for
subsequent calls to ODMA functions.
|
None.
A DMS interfaces with ODMA through a function called ODMGetODMInterface
and
through three COM interfaces; IODMDocMan
,
IODMQuery
and IODMDocMan2
. When an
application calls the ODMA connection manager's ODMRegisterApp
function, the
connection manager calls the appropriate DMS's ODMGetODMInterface
function to
establish a connection with the DMS.
The IODMDocMan
interface implements all of the basic document management
functionality defined by the ODMA 1.0 specification. The IODMQuery
interface
implements the query extension of the ODMA 1.5 specification. The IODMDocMan2
interface implements the extended document management functionality defined in
the ODMA 2.0 specification. The methods of these interfaces each correspond
directly with a function from the ODMA API section of this document. (For
example, the SelectDoc
method of the IODMDocMan
interface corresponds to the
ODMSelectDoc
function.) With only one exception, the functionality of each
method is completely detailed by the description of its corresponding ODMA API
function. For that reason, this section of the document only provides a list
of each method with its prototype and no further details. (The one exception
is the QueryExecute
method of the IODMQuery
interface. Additional details,
only important to the DMS’s implementation of this method, are provided below.)
HRESULT ODMGetODMInterface( REFIID riid, LPVOID FAR *ppvObj, LPUNKNOWN pUnkOuter, LPVOID pReserved, LPSTR lpszAppId, DWORD dwEnvData )
The ODMA connection manager calls this function to get an interface from a
DMS. This function is not available to ODMA-aware applications. The DMS
returns its status using OLE HRESULT
codes which the Connection Manager then
maps to ODMA status codes.
|
|
|
|
|
|
|
|
|
|
|
SelectDoc
STDMETHOD_( ODMSTATUS, SelectDoc ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags ) PURE;
OpenDoc
STDMETHOD_( ODMSTATUS, OpenDoc ) ( THIS_ DWORD flags, LPSTR lpszDocId, LPSTR lpszDocLocation) PURE;
SaveDoc
STDMETHOD_( ODMSTATUS, SaveDoc ) ( THIS_ LPSTR lpszDocId, LPSTR lpszNewDocId) PURE;
CloseDoc
STDMETHOD_( ODMSTATUS, CloseDoc ) ( THIS_ LPSTR lpszDocId, DWORD activeTime, DWORD pagesPrinted, LPVOID sessionData, WORD dataLen) PURE;
NewDoc
STDMETHOD_( ODMSTATUS, NewDoc ) ( THIS_ LPSTR lpszDocId, DWORD dwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation ) PURE;
SaveAs
STDMETHOD_( ODMSTATUS, SaveAs ) ( THIS_ LPSTR lpszDocId, LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, LPVOID pInstanceData) PURE;
Activate
STDMETHOD_( ODMSTATUS, Activate ) ( THIS_ WORD action, LPSTR lpszDocId) PURE;
GetDocInfo
STDMETHOD_( ODMSTATUS, GetDocInfo ) ( THIS_ LPSTR lpszDocId, WORD item, LPSTR lpszData, WORD dataLen ) PURE;
SetDocInfo
STDMETHOD_( ODMSTATUS, SetDocInfo ) ( THIS_ LPSTR lpszDocId, WORD item, LPSTR lpszData ) PURE;
GetDMSInfo
STDMETHOD_( ODMSTATUS, GetDMSInfo ) ( THIS_ LPSTR lpszDmsId, LPWORD pwVerNo, LPDWORD pdwExtensions) PURE;
GetLeadMoniker
STDMETHOD_( ODMSTATUS, GetLeadMoniker ) ( THIS_ LPSTR lpszDocId, LPMONIKER FAR *ppMoniker) PURE;
QueryExecute
STDMETHOD_( ODMSTATUS, QueryExecute ) ( THIS_ LPCSTR lpszQuery, LPSTR dmsQueryId ) PURE;
Additional Notes: Upon success, the string returned in
dmsQueryId
should be
of the form: "::ODMA\DM_ID\DMS_SPECIFIC_QUERY_ID>"
. Note that this
query ID
is not necessarily the one returned to the client
application. Note also that
multiple query IDs from different DMSs will be mapped to the same query ID for
a single query call from the client application. The dmsQueryId
string may be
up to ODM_DOCID_MAX bytes in length.
The return value of ODM_E_PARTIALSUCCESS
is a valid
return value for
ODMQueryExecute
but is not a valid return value for this
method.
QueryGetResults
STDMETHOD_( ODMSTATUS, QueryGetResults ) ( THIS_ LPCSTR queryId, LPSTR lpszDocId, LPSTR lpszDocName, WORD docNameLen, LPWORD pwDocCount ) PURE;
QueryClose
STDMETHOD_( ODMSTATUS, QueryClose )( THIS_ LPCSTR dmsQueryId ) PURE;
CloseDocEx
STDMETHOD_( ODMSTATUS, CloseDocEx ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags, DWORD activeTime, DWORD pagesPrinted, LPVOID sessionData, WORD dataLen) PURE;
SaveAsEx
STDMETHOD_( ODMSTATUS, SaveAsEx ) ( THIS_ LPSTR lpszDocId, LPSTR lpszNewDocId, LPSTR lpszFormat, ODMSAVEASCALLBACK pcbCallBack, LPVOID pInstanceData, LPDWORD pdwFlags) PURE;
SaveDocEx
STDMETHOD_( ODMSTATUS, SaveDocEx ) ( THIS_ LPSTR lpszDocId, LPSTR lpszNewDocId, LPDWORD pdwFlags) PURE;
SelectDocEx
STDMETHOD_( ODMSTATUS, SelectDocEx ) ( THIS_ LPSTR lpszDocIds, LPWORD pwDocIdsLen, LPWORD pwDocCount, LPDWORD pdwFlags, LPSTR lpszFormatFilter ) PURE;
QueryCapability
STDMETHOD_( ODMSTATUS, QueryCapability ) ( THIS_ LPCSTR lpszDmsId, DWORD function, DWORD item, DWORD flags ) PURE;
SetDocEvent
STDMETHOD_( ODMSTATUS SetDocEvent ) ( THIS_ LPSTR lpszDocId, DWORD flags, DWORD event, LPVOID lpData, DWORD dwDataLen, LPSTR lpszComment) PURE;
GetAlternateContent
STDMETHOD_( ODMSTATUS GetAlternateContent ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation ) PURE;
SetAlternateContent
STDMETHOD_( ODMSTATUS SetAlternateContent ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszFormat, LPSTR lpszDocLocation ) PURE;
GetDocRelation
STDMETHOD_( ODMSTATUS GetDocRelation ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, LPSTR lpszPreviousId ) PURE;
SetDocRelation
STDMETHOD_( ODMSTATUS SetDocRelation ) ( THIS_ LPSTR lpszDocId, LPDWORD pdwFlags, LPSTR lpszLinkedId, LPSTR lpszFormat, LPSTR lpszPreviousId ) PURE;
The ODMA connection manager, ODMA.DLL
(Windows 3.x) or
ODMA32.DLL
(Windows
95 and NT), and a corresponding link library, ODMA.LIB
(Windows 3.x) or
ODMA32.LIB
(Windows 95 and NT), will be made freely available to any
application vendor wishing to use them. Applications can choose either of the
methods described below to bind to ODMA:
1. Link to ODMA.LIB
/ODMA32.LIB
. Applications choosing this approach will
need to install a copy of ODMA.DLL
/ODMA32.DLL
into the Windows system
directory at the time the application is installed unless a newer copy of ODMA.DLL
/ODMA32.DLL
already resides there. At startup time the application can
call ODMRegisterApp
to determine whether or not an ODMA provider is present
for the calling application.
2. Dynamically load ODMA.DLL
/ODMA32.DLL
at startup time with a call to
LoadLibrary
. With this approach the application has to call GetProcAddress
to
get a pointer to each ODMA function it will call, but the application does not
have to do anything related to ODMA at installation time. If ODMA.DLL
/ODMA32.DLL
doesn't exist or if
ODMRegisterApp
returns ODM_E_NODMS
then the application knows that no ODMA provider is present for the calling
application.
There is currently no thunk layer that exists to allow a 32-bit application and a 16-bit DMS, or vice versa, to interact with each other.
The ODMA connection manager, ODMA.DLL
for Windows 3.x and
ODMA32.DLL
for
Windows NT and Windows 95, will be provided to all DMS vendors that want to
support the ODMA specification. These DLLs will serve as a common entry point
for applications that wish to call ODMA functions. Its implementation of
ODMRegisterApp
will figure out which DMS is registered for default use by the
calling application. It will then load the appropriate DMS's DLL and pass
through the function call. All other ODMA function calls that do not include a
document ID will be passed to this default DMS.
When an ODMA call is made that includes a document
ID, the ODMA connection
manager will determine which DMS created the ID. If that DMS has not been
initialized yet by the calling application, the connection manager will call
the provider's ODMGetODMInterface
function and will then pass through the
current ODMA function call.
As part of its installation, a DMS should check whether a copy of ODMA.DLL
and/or ODMA32.DLL
already exists in the Windows System directory. (On Windows
NT the ODMA32.DLL
belongs in the System32 directory.) If the DLLs do not exist
or if the DMS has newer versions then it should copy its version of ODMA.DLL
and/or ODMA32.DLL
to the Windows System directory. As of ODMA 2.0, the
Connection Manager DLLs will contain version resource information. Next the
DMS should register with the ODMA connection manager by adding one or more
keys to the registration database.
Each DMS must add a subkey to the root level ODMA key. This subkey should
be named the same as the DMS's DMS ID, and the subkey's value should specify
the location of the DLL containing the DMS's ODMA entry points. For example,
suppose a DMS with a DMS ID of DDD
implemented its ODMA entry points in
H:\ABC\XYZ.DLL
. It would add the following key and value to the registration
database under the HKEY_CLASSES_ROOT
key:
ODMA\DDD
=H:\ABC\XYZ.DLL
for Windows 3.xODMA32\DDD
=H:\ABC\XYZ.DLL
for Win32 (i.e. WinNT & Windows 95)
The DMS ID is limited to 8 characters and is often cryptic. The DMS must
add a FullName
subkey under its DMS ID subkey which provides the full name of
the DMS. The DMS is free to include any information necessary in the FullName
(i.e. vendor name, version and platform). For example, our fictional DMS with
the DDD
DMS ID would define FullName
like this:
ODMA\DDD\FullName
="Dynamic Document Depot V1.0 for Windows"
ODMA32\DDD\FullName
="Dynamic Document Depot V1.0 for Windows"
Applications should never display a DMS ID in a user interface. These DMS
IDs can be obtained using ODMGetDMSList
or directly reading the registration
database. Applications should look up the FullName
of the DMS and display that
instead.
If the DMS wanted to serve as the default ODMA provider to be used with all
ODMA-aware applications that were not registered with a specific DMS, it would
add the DEFAULT
subkey to its DMS ID key as shown below:
ODMA\DDD\DEFAULT
for Windows 3.xODMA32\DDD\DEFAULT
for Win32 (i.e. Windows NT and Windows 95)
If the DMS wanted to specifically register itself as the ODMA provider for
one or more applications, it would also add a subkey to the relevant
applications' root level keys. Note that this is only necessary if a different
DMS is registered as the default ODMA provider. Each time an application calls
ODMRegisterApp
, the connection manager looks in the registration database for
a root-level key that matches the specified application ID. If it finds such a
key then it looks under it for a subkey called ODMA
. The value of this key is
the DMS ID of the specifically registered DMS. If the application ID key is
not found or if the subkey ODMA
or ODMA32
does not exist under it, the
connection manager looks at the subkeys of the root-level key ODMA
or
ODMA32
for a default ODMA implementation.
For example, suppose a document management system with a DMS ID of DDD
wanted to support only one particular application that used QQQ
as its
application ID. It would add the following key and value to the registration
database in addition to the ODMA
subkey described above:
QQQ\ODMA
=DDD
for Windows 3.xQQQ\ODMA32
=DDD
for Win32 (i.e. Windows NT and Windows 95)
This section defines the registration database entries ODMA compliant client applications should make when they are installed. These entries will help provide improved out-of-the-box integration between applications and Document Management Systems. They will allow an application to:
Most Document Management and Workflow Management applications have a
function that can push a document to the native application which supports the
document’s content format. The Windows platform provides several functions
which can be used to launch an application to open a document. Examples are
ShellExecute
, WinExec
and CreateProcess
(Win32 only). However, the calling
application needs to be able to determine in a seamless way if it should be
passing a file specification or an ODMA Document ID to the application. For
this reason, applications which support an ODMA Document ID in their command
line or DDE interface must record this information in the registration
database.
In addition to the above, the calling application may need to know if the ODMA application to be launched is 16-bit or 32-bit. For example, if the calling DMS application is only 16-bit and the application to be launched is 32-bit, then perhaps the calling application can downgrade to some other form of application invocation that doesn’t required a 32-bit DMS.
File type entries take the following form, under the HKEY_CLASSES_ROOT
key:
ODMA.FileTypes\<FileType>
=
"<AppSubkey>
"ODMA32.FileTypes\<FileType>
=
"<AppSubkey>
"
<FileType>
is the same value used in the HKEY_CLASSES_ROOT\.ext
entry
for the file extension. Sometimes this value is referred to as a file type
class name. This provides a link back to the file type’s other registration
entries. Note that often applications have more than one file extension
pointing to a single file type class name.
<AppSubkey>
is the same as the ODMA application’s
AppId, used in
ODMRegisterApp
. If the AppId contains spaces they must be removed, because
spaces are not allowed in a subkey.
Application entries are as follows (under the HKEY_CLASSES_ROOT
key):
ODMA.ClientApps\<AppSubkey>
=
"<AppId>
"ODMA32.ClientApps\<AppSubkey>
= "<AppId>
"
The <AppSubkey>
is the same as above. The
<AppId>
is the
regular string used by the application in ODMRegisterApp
. It can contain
spaces and is limited to 15 characters (see the ODM_APPID_MAX
constant).
The FullName
of a client application can be provided as follows:
ODMA.ClientApps\<AppSubkey>\FullName
=
"The app name
"ODMA32.ClientApps\<AppSubkey>\FullName
=
"The app name
"
Use the following procedure to determine if the application that supports a
given file type can also handle an ODMA document ID in its command line or DDE
interface. First lookup the file extension entry in the Registry to get the
file type class name. If the extension isn’t found then there is no
application supporting the file type on the system. Next append the file type
class name to the ODMA32.FileTypes\
key and see if the key exists in the
registry. If the key exists, then a 32-bit ODMA-aware application that can
accept an ODMA document ID in its command line or DDE interface should be
present on the system. If the key was not found then the ODMA.FileTypes
key
can be tested to determine if a 16-bit ODMA-aware application is present. If a
16-bit DMS client is initiating this process, it can avoid launching a 32-bit
application if it doesn’t have the correct thunking layers installed on the
platform. The reverse is also true, where a 32-bit DMS might avoid launching a
16-bit application if it does not support 16-bit ODMA on the platform.
As of ODMA 2.0, the ODMA Connection Manager is capable of logging function
calls made by any application to any DMS on the system. This trace log
contains information about each function call made, including the App ID of
the calling application and the input values of individual function
parameters. It also includes the information returned by the DMS, like
function values and output parameter values. The trace log contains
information about function calls that are handled by the Connection Manager
without DMS involvement (i.e. ODMGetDMS
,
ODMSetDMS
, ODMGetDMSList
, etc.).
The following Windows Registry sub-keys, under HKEY_CLASSES_ROOT
, control
ODMA trace logging:
ODMA.ConnectionManager\Logging\Enabled
ODMA32.ConnectionManager\Logging\Enabled
If the entire sub-key described above is defined then the Connection
Manager will do trace logging. To disable trace logging simply remove the
"Enabled
" sub-key. There are no default data names or values assigned to this
sub-key at this time.
ODMA.ConnectionManager\Logging\File
= "fullpath
"ODMA32.ConnectionManager\Logging\File
= "fullpath
"
The default filename for the trace log file is "ODMA.LOG
" for the 16-bit
Connection Manager and "ODMA32.LOG
" for the 32-bit Connection Manager. The
default path is the Windows System or System32 directory as appropriate. If
the File
sub-key does not exist then ODMA uses its defaults. If the
fullpath
is specified in the data value it must contain a full path and filename. If
the fullpath
is invalid the Connection Manager will revert to its default log
filename and path.
ODMA.ConnectionManager\Logging\Options
= "token1,token2
"ODMA32.ConnectionManager\Logging\Options
=
"token1,token2
"
The Options data value is simply a comma separated string of tokens. There is no default value defined at this time. The various tokens control trace logging. They are:
NEWLOG
-- If defined then when the Connection Manager DLL is loaded into
memory it will delete any existing log file and create a new log file. The
default behavior is for the Connection Manager to append to any existing log
file.
The following table describes document attributes or properties defined by
ODMA. Applications can get attribute values for a document by using the
ODMGetDocInfo
function. Some attribute values can be set using the
ODMSetDocInfo
function. Not every DMS will support every document attribute
listed here. Applications can use the ODMQueryCapability
function to determine
if a DMS supports a given document attribute.
Note that the ODMA standard does not currently define maximum lengths for any specific document attribute. This is DMS specific. In most cases the DMS will truncate the attribute value returned if it does not fit in the caller supplied buffer.
Attribute/Item ID | Description | Type | Set |
ODM_ALTERNATE_RENDERINGS |
If the DMS supports alternate renderings for
the specified document, then it must return a comma-separated list of
format names representing the alternate formats it can return in
ODMGetAlternateContent . Refer to the Document Format Names section for
information on how file formats are identified in ODMA. |
String | No |
ODM_AUTHOR |
Author of the document. | String | Yes |
ODM_CONTENTFORMAT |
The format name string indicating the format
of the document’s contents. Refer to the Document Format Names section
for information on how file formats are identified in ODMA. In
ODMGetDocInfo It is recommended that the DMS return either a MIME
Content Type or a Windows file type/extension. Note that when this item
is used in ODMSetDocInfo , it merely informs the DMS of a change in the
document's format; it does not cause a conversion process to take place
within the DMS. |
String | Yes |
ODM_CHECKEDOUTBY |
Username of the person who has the document checked-out. This username is in the form used by the DMS. If the document is not currently checked-out a zero length string is returned. | String | No |
ODM_CHECKOUTCOMMENT |
The comment, if any, that the user supplied when they checked-out the document. | String | No |
ODM_CHECKOUTDATE |
The date/time the document was checked-out. If the document isn’t currently checked-out, a zero-length string is returned. | Date | No |
ODM_CREATEDBY |
Username of the person who initially created the document in the DMS. | String | No |
ODM_CREATEDDATE |
The date/time the document was created in the DMS. | Date | No |
ODM_DOCID_LATEST |
A null-terminated document ID for the Latest
version of the document represented by lpszDocId . If
lpszDocId is the
Latest version, it will be the same document ID. |
DocId | No |
ODM_DOCID_RELEASED |
A null-terminated document ID for the
Released version of the document represented by lpszDocId . If
lpszDocId
is the Released version, it will be the same document ID. If the DMS
does not differentiate Released versions, return the version ID of the
Latest version of the document. A DMS may allow this attribute to be
set. An application such as a workflow can set a version of a document
to be the released version by specifying this attribute in a call to
ODMSetDocInfo . In this case, the lpszData parameter should be set to
Null. |
DocId | Yes |
ODM_DOCVERSION |
A null-terminated string which is the version
ID for lpszDocId . This allows the application to display the version
information explicitly (without doing the impossible and decoding the
document ID), for situations such as where the user is making the
decision to re-link to a different version. It is the DMS responsibility
to consistently translate version information into a string that can be
used for comparison and display. Since it is a string, and comparisons
will not be made between strings from different DMS, the application
does not have to be concerned that different DMS have different formats,
meanings and capabilities for version, sub-version, branching and so on.
|
String | No |
ODM_DOCVERSION_LATEST |
A null-terminated string which is the version
ID for the Latest version of the document represented by lpszDocId . |
String | No |
ODM_DOCVERSION_RELEASED |
A null-terminated string which is the version
ID for the Released version of the document represented by lpszDocId .
If the DMS does not differentiate Released versions, return the version
ID of the Latest version of the document. |
String | No |
ODM_LOCATION |
A null-terminated string containing DMS
specific information describing the logical location (e.g. folder) of
the document within the data store. The DMS should format the
information in this attribute so that it can be safely displayed in a
user-interface. The application should not assume the information in
this attribute is persistent across ODMA sessions. A DMS may allow an
application to set this attribute in ODMSetDocInfo only for documents
that have not been created yet. |
String | Yes |
ODM_KEYWORDS |
A comma separated list of keywords assigned to the document. | String | Yes |
ODM_LASTCHECKINBY |
Username of the last person to modify or check-in the document. | String | No |
ODM_LASTCHECKINDATE |
The date/time the document was last modified or checked-in. | Date | No |
ODM_MODIFYDATE |
The data/time the document was last modified. | Date | No |
ODM_MODIFYDATE_LATEST |
The date/time that the Latest version of the document was last modified. | Date | No |
ODM_MODIFYDATE_RELEASED |
The date/time that the version of the document that is Released was last modified. If the DMS does not differentiate Released versions, return the date/time that the Latest version of the document was last modified. | Date | No |
ODM_NAME |
Name of the document. This is a descriptive name for the document, not the filename. | String | Yes |
ODM_OWNER |
The owner of the document. | String | No |
ODM_SUBJECT |
The subject matter of the document. | String | Yes |
ODM_TITLETEXT |
Suggested text to display in the document window's title bar. This may include one or more fields from the document's profile and possibly other information as well. | String | No |
ODM_TITLETEXT_RO |
Same as ODM_TITLETEXT , except if the document
is currently opened by the calling application in ODM_VIEWMODE , the DMS
should append " (Read-Only)" to the text. |
String | No |
ODM_TYPE |
Type of the document. This is typically an indication of the format or content of the document, i.e. correspondence, memo, contract, etc. | String | Yes |
ODM_URL |
Uniform Resource Locator (URL) which provides an alternative way to access the document. Note that a DMS can never truncate a URL if it is too long to fit into the caller supplied buffer. | String | No |
"YYYYMMDDhhmmsscc +hhmm"
. "YYYYMMDD"
section contains a 4 digit
year, 2 digit month and 2 digit day. The "hhmmsscc"
section contains the time
in 24 hour format (hours, minutes, seconds, hundredths of seconds). A DMS
should return zeros for any part of a time it doesn’t support. The "+hhmm"
section is an optional Greenwich Mean Time (GMT) offset. If the GMT string is
included in a date/time string it is preceded by a space, followed by either a
+
(plus) or -
(minus) character, then a 2 digit hour value and a 2 digit
minute value. A DMS should only return the GMT offset if it knows the offset
for the data store containing the specified document. If the GMT offset is not
included, then the date/time value is the local date and time for the document
in the DMS.DocId = A null-terminated string containing an ODMA document ID.
The "Set" column indicates if the attribute can be set with
ODMSetDocInfo
.
It is possible that a DMS may not allow certain document attributes to be set.
There has been some misunderstandings among both DMS and application vendors on the correct use of the ODMA 1.0 calls to initially create a file. This appendix is basically from a proposal made in October 1994 by Rod Schiffman of Novell. There has been no dissension on the issue since the original proposal was made. Until the standard is modified to provide other methods for the initial creation of a new document in a DMS, this provides a sequence for the calls that will work with all major DMS vendors.
It is probably useful for me to describe the terminology and concepts I will use in this discussion. A DMS is fundamentally more complex than my description, but it will suffice for my purposes. A DMS is a black box that manages documents. My Local System is the particular machine and Operating System, or environment, that I use. It has its own file system, applications and interfaces. When I need to do something to a existing document in the DMS, I select it using tools the DMS provides and retrieve it into my local system. I use an application to perform operations on the document. I may want to create a new document with my application. The new document will be stored on my local system until I save it into the DMS. The DMS may want to tell me where I should save it on the Local System until I eventually save it into the DMS. I may also want to update the copy in the DMS while I am still working on it. I call this writing the document through to the DMS. When I am finally done working on the document, I can save it to the DMS. It is then closed. At some point in the process of creating a new document, the DMS will require me to give it a profile. When I have saved the document to the DMS, it is closed and the document no longer has a presence on my local machine. ODMA has a vaguely defined concept of formats that are attached to a document, and while the timing of when and how formats are defined plays a central role in this discussion, formats, conversions and their association to documents does not play a role in this discussion.
ODMSaveDoc
is the only ODMA function that actually saves a document into a
DMS. It uses a Document ID (DocID) supplied by the DMS. The initial creation
of the first DocID for the document can only be supplied by ODMNewDoc
.
ODMSaveAs
and ODMSaveDoc
can return a new DocID, but they must already have an
initial DocID to start with. ODMSelectDoc
only returns a DocID that already
exists. This means that ODMNewDoc
must be called to generate the initial
DocID. After the application has a DocID, it can call ODMOpenDoc
to get a
local file name to save the document to and ODMSaveDoc
to write the document
through to the DMS. This would imply that it is not necessary to call
ODMSaveAs
in the process of saving the document the first time. This has
caused a number of people to assume that the usage of ODMNewDoc
was synonymous
with the initial "Save" function in most applications. However, the spec says
that the format specified in ODMNewDoc
"may be changed later via an
ODMSaveAs
call." This implies that it is OK to call ODMSaveAs
after calling
ODMNewDoc
.
ODMSaveAs
is the only call that allows an application to interact with the DMS
and supply application specific information such as formats and passwords. If
an app only calls ODMNewDoc
and does not call
ODMSaveAs
, it loses the ability
to provide application specific information. ODMSaveAs
requires that a user
interface is supplied to the user. If ODMNewDoc
also supplies a user
interface, then the user interface comes up twice for each document creation.
Once in ODMNewDoc
and again in ODMSaveAs
. This is probably not something that
the user wants. Also, how do we reconcile the ability to call ODMNewDoc
without a user interface. If ODMNewDoc
is called with no user interface and a
DocID is returned, then when is the profile filled in? ODMOpenDoc
and
ODMSaveDoc
and ODMCloseDoc
have no obvious provisions for providing a user
interface.
ODMNewDoc
was originally intended to be synonymous with the "New" menu
choice, not the "Save" menu choice, in most applications. For example,
although SoftSolutions and PC Docs do not care about a document until it is
time to save it to the DMS the first time, DEC TeamLinks does have the concept
of letting the DMS know a document is going through initial creation. There is
nothing in the spec that indicates whether ODMNewDoc
should be called at
document creation or just before saving the document the first time. This is
not an accident according to Brad Clements, the original author of the ODMA
spec. It can be done at whatever time makes sense for the DMS and application.
ODMNewDoc
does not have provisions for the callback routine because it
notifies the DMS about the creation of a document not the saving of a
document. At document creation time, the user is probably not worried about
the what the final format will be or if there will be a password. The user may
not, and this is crucial, even save the document to the DMS. It is possible
that if ODMNewDoc
is called without a user interface, that the
DocID returned
to the application may not eventually be used, if the user is allowed to have
the file saved to the local file system in a later call to ODMSaveAs
.
It turns out that many applications and Document Management Systems do not have or need a concept of providing application and DMS interaction until the document is ready to be saved in the DMS for the first time. Certainly a DMS must deal with applications that will not provide any interaction with the DMS until the document is already created in the edit buffer and is ready to be saved. At this point I would like to point out a scenario that follows the spec, and still works with major applications that may not have followed the spec according to the interpretation given here.
At the time of initial document creation, or when it is time to save the
document the application should call ODMNewDoc
with the
ODM_SILENT
flag. This
will return a temporary DocID that the application can use. Technically, the
application could call ODMOpenDoc
to have a local temporary file to use until
the document is finally saved into the DMS, but I know that every DMS vendor I
have talked to would frown on this idea. They prefer the idea that all saves
are written through to the DMS and that there is a full profile for anything
that exists in the DMS. It is OK for the DMS vendor require this by returning
an ODM_E_USERINT
error to indicate that
ODMOpenDoc
cannot be called until the
app makes a call to ODMNewDoc
or
ODMSaveAs
that brings up an user interface.
This implies that the application would be better to avoid the situation and
not call ODMOpenDoc
until after an user interface is provided to the user.
After calling ODMNewDoc
in silent mode, take the
DocID that is returned and
call ODMSaveAs
to have the profile created, and allow access to the callback
routines. If the ODMNewDoc
returns an
ODM_E_USERINT
error because it does not
support the silent mode, then call ODMNewDoc
with a user interface and skip
calling ODMSaveAs
. This performs the same functionality, but does not provide
access to the callback routines. If the application still wants the user to
see the callback dialog, then it can call the callback dialog itself after
calling the ODMNewDoc
call. This is not optimal, but does work. In either case
the user interface is only presented to the user one time.
There are a couple caveats for DMS vendors. The DocID returned by ODMNewDoc
must be a temporary ID. It is possible that the user will throw away the file
before it is saved, or that it will be saved to the native OS through the
options button in the SaveAs dialog. This could be easily handled by returning
a well known dummy value like ::ODMA\<app id>\NULL
. When
ODMSaveAs
sees
this null value as the DocID, it can know that it is creating the document for
the first time and take appropriate action as opposed to the normal SaveAs
action. It does not matter if there are multiple documents using this DocID at
the same time as long as the DMS returns ODM_E_USERINT
to the
ODMOpenDoc
call
that passed in the null DocID.
Basically, this turns the ODMNewDoc
into a fancy NOP routine. There may be
situations where this may not be the best action, but since there is no
compelling reason for the existence of the ODMNewDoc
call in the 1.0 spec, it
seems to solve more problems than it creates. It would probably be a good idea
to add an extension to the 1.0 spec in ODMA 1.1 where the ODMSaveAs
call can
allow a NULL
to be passed in as the lpszDocID
parameter to indicate that the
document is being saved for the first time. This would free the application
from having to use the ODMNewDoc
call. Of course, that is what the addition of
a dummy DocID value returned from ODMNewDoc
accomplishes. In the ODMA 1.1
time-frame a new ODMNewDoc
call can be created if someone comes up with a
compelling reason for its existence. Simply using the ODMSaveAs
call when an
application is creating a new file in the DMS, whether it is the first save or
an actual SaveAs, matches the way most applications work today.
ODMA 2.0 introduces an ODMSaveAsEx
function that extends
ODMSaveAs
. This
addresses the specification change Rod Schiffman had envisioned. The
lpszDocId
parameter in ODMSaveAsEx
can optionally be set to Null by the calling
application. This frees the application from calling ODMNewDoc
during a Save
As sequence for a new document. If the application calls ODMSaveAsEx
without
first calling ODMNewDoc
, then the DMS will return a
DocID in the lpszNewDocId
parameter. This may be a temporary DocID that will later be replaced by a new
DocID when ODMSaveDoc
or ODMSaveDocEx
is called.
Note that there is a purpose for the ODMNewDoc
call in the Save As
sequence. The temporary DocID returned by the DMS in ODMNewDoc
will provide a
document context which the application can use to pre-set some document
attributes for the new document before calling ODMSaveAs
or
ODMSaveAsEx
. This
is the only way for an application to pre-set items that might appear in the
DMS’s Save As dialog box. Examples of such attributes are ODM_AUTHOR
,
ODM_NAME
, ODM_TYPE
,
ODM_KEYWORDS
, ODM_SUBJECT
and perhaps others. The
application can set these attributes by calling ODMSetDocInfo
using the
DocID
returned by ODMNewDoc
. The application can call
ODMQueryCapability
to find
out if the DMS will accept the attributes in ODMSetDocInfo
. However, there is
no way for an application to know if the attributes will be visible in the
DMS’s Save As dialog box.
The ODMA 2.0 specification also introduces a way to create documents
without user interaction. The new ODMSaveAsEx
,
ODMSaveDocEx
and ODMCloseDocEx
functions all have an ODM_SILENT
flag for this purpose. As outlined
above,
ODMNewDoc
is used to create a temporary document context and ODMSetDocInfo
is
used to set document attributes.
Additionally, ODMA 2.0 recommends a standard for applications and DMSs to use to identify file format types.
created 1997 September 17
$$Date: 07-07-18 13:37 $
$$Revision: 75 $