BONDI API Design Patterns specify the common rules governing all the APIs defined in BONDI Interfaces documents.
The BONDI initiative defines a set of Application Programming Interfaces (APIs). All the interfaces are defined in WebIDL, combined with documentation formatted using doxygen-like syntax. BONDI Interfaces are grouped into modules, where each module defines a set of related WebIDL interfaces. Each BONDI module is defined in a single file with the extension ".widl". Both WebIDL and doxygen-like documentation are combined in the same file.
Since the number of BONDI modules is considerable and is likely to grow in the future, it is necessary to specify common rules that will govern how both the WebIDL content and doxygen-like documentation are structured. This will ensure consistency throughout all BONDI APIs. This document specifies those rules and guidelines.
The WebIDL patterns section defines the rules that are applicable to the WebIDL parts of .widl files, whereas the Documentation patterns section defines the rules that are applicable to the doxygen-like parts of .widl files.
WebIDL allows methods, getters and setters to raise not only exceptions, but also objects that expose given interfaces. WebIDL exceptions cannot be inherited and therefore no hierarchy of exceptions can be built. However, within BONDI each module is able to define its own error interface. Thus, to support hierarchy of errors within BONDI, we are going to use only error interfaces for which a specific inheritance hierarchy has been built.
WebIDL definition
interface Error {
readonly attribute DOMString name;
readonly attribute DOMString message;
};
interface GenericError : Error {
readonly attribute unsigned short code;
};
interface DeviceAPIError : GenericError {
const unsigned short UNKNOWN_ERROR = 10000;
const unsigned short INVALID_ARGUMENT_ERROR = 10001;
const unsigned short NOT_FOUND_ERROR = 10002;
const unsigned short PENDING_OPERATION_ERROR = 10003;
const unsigned short IO_ERROR = 10004;
const unsigned short NOT_SUPPORTED_ERROR = 10005;
};
interface SecurityError : GenericError {
const unsigned short PERMISSION_DENIED_ERROR = 20000;
};
ECMAScript methods can be either synchronous or asynchronous. Methods using the synchronous mode of operation do not return control to the caller until the operation is complete. Asynchronous methods return immediately and notify the caller at some point in the future of the results via callback method(s). The callback methods are specified as parameters to the asynchronous method. The following rules describe how to specify asynchronous methods in BONDI WebIDL.
WebIDL definition
[Callback] interface SuccessCallback {
void onSuccess(in Object ob);
};
[Callback] interface ErrorCallback {
void onError(in Error error);
};
interface PendingOperation {
boolean cancel();
};
It is assumed that the BONDI interfaces will evolve over time. The interfaces defined within BONDI Release 1.0 may be modified in future releases of the BONDI specifications. They may add new methods or attributes, they may remove them or modify the way they operate. Therefore a versioning model is defined that will enable widgets to be installable and to function properly on WUAs that are equipped with the appropriate implementation of the APIs.
iquery = *( ipchar / iprivate / "/" / "?" )For the purpose of BONDI API versioning, the iquery - being just a series of characters within RFC3987 - get further specification as follows:
iquery = iqueryversion / iqueryversionrange / iquerynext iquerynext = *( ipchar / iprivate / "/" / "?" ) iqueryversion = %x76.3d DIGIT *(DIGIT) %x2e DIGIT *(DIGIT) %x2d DIGIT *(DIGIT) %x2e DIGIT *(DIGIT) %x3f iquerynext iqueryversionrange = %x76.3d DIGIT *(DIGIT) %x2e DIGIT *(DIGIT) %x3f iquerynext
It should be noted that iquery is the non-hierarchical part of IRI, therefore it is able to provide versioning to all parts of the IRI used throughout BONDI specifications, include BONDI Architecture & Security. By using the query part, we state that we mean the same resource (i.e. API), but we refer to some specific version of it (IRI semantics).
Query being non-hierarchical allows for defining APIs (being hierarchical) to be grouped by the query part, thus being orthogonal to the API hierarchies.
This pattern is used in bondi.requestFeature(..,..,IRI) and in the <feature> element in config.xml.The following IRI identifies filesystem read operations from BONDI 1.0 specification:
http://bondi.omtp.org/api/filesystem.read?v=1.0The following IRI identifies filesystem read operations from BONDI 1.0 through BONDI 2.0 specifications:
http://bondi.omtp.org/api/filesystem.read?v=1.0-2.0.In the latter case it is assumed that either there were no changes to the filesystem read operations between BONDI versions 1.0 and 2.0 or that the requester is using only those parts that are common in both of them.
/**
* \brief Messaging specific error callback.
*
* This callback error interface is specific to this messaging API. It
* specifies a error callback with a function taking an MessagingError object
* input argument.
*/
[Callback] interface MessagingErrorCallback {
void onError(in MessagingError error);
};
The documentation syntax MUST begin with the line that includes only "/**" and white-space characters (space, tab or new line). Each of the subsequent documentation lines MUST begin with "*" and the final documentation line MUST consist of only "*/" and white-space characters. Each line of the documentation MAY include up to one keyword, i.e. a token prefixed with the backslash ("\") character. The following keywords are available for BONDI widl documentation:
The PendingOperation interface MUST also be specified in bondi.widl.
/**
* \brief
*
* 'module description'
*
* \def-api-feature 'API Feature Identifier'
* \brief 'API Feature brief description'
*
* 'API Feature detailed description (optional, blank line above not needed if absent)'
* \device-cap 'Identifier of related Device Capability'
* 'optional brief description of circumstance in which that device cap is used'
*
* ...
* \def-device-cap 'Device Capability Identifier'
* \brief 'Device capability brief description'
*
* 'Device Capability detailed description (optional, blank line above not needed if absent)'
* \param 'security parameter name' 'brief description'
* ...
*
* \author 'Name' 'e-mail'
* \version 'API version'
*
*/
module foo {
...
};
/**
* \brief 'Brief interface description'
*
* 'Detailed description of the interface'
*
* \code
* 'Code Example'
* \endcode
*/
interface fooInterface {
...
}
For instance, in the case of the FileSystemManager Interface
/**
* \brief FileSystemManager API.
*
* This file system API provides basic filesystem access.
*
* \code
* var dir = bondi.filesystem.mount(fs.getDefaultLocation("app:public"));
* var files = dir.listFiles();
* for(var i = 0; i < files.length; i++) {
* alert(files[i].name); // displays name of each file in directory
* }
* var file = dir.createFile("test.txt");
* var out = file.open("w", "UTF-8");
* // writes Hello World to test.txt
* out.write("Hello World");
* out.close();
* \endcode
*/
interface FileSystemManager {
Additionally, read-write attributes MUST include a description of the possible errors and the conditions in which they are raised when setting or getting the value of the attribute based on the setraises or getraises WebIDL keywords.
/**
* \brief 'brief attribute description'
*
* 'detailed attribute description'.
* This attribute is read-only
* \code
* 'example code'
* \endcode
*/
readonly attribute 'type' 'name'
/**
* \brief Contains the implementation dependent maximum path length.
*
* This attribute is read-only.
*
* \code
* alert(bondi.filesystem.maxPathLength);
* \endcode
*/
readonly attribute long maxPathLength;
/**
* \brief 'brief attribute description'
*
* 'detailed attribute description'.
* This attribute is read-only
*
* \code
* 'example code'
* \endcode
* \throw 'error object and code to be thrown' 'conditions in which is thrown'
*/
attribute 'type' 'name'
setraises('errorobject');
/**
* \brief Get/set current position in this stream.
*
* The position of this stream is an offset of bytes from the start
* of the file stream. When invoking an operation that reads or writes
* from the stream, the operation will take place from the position
* in the position attribute.
*
* \code
* alert(stream.position); // displays current stream position
* // alters current stream position to the begin of the file,
* // like seek() in C
* stream.position = 0;
* \endcode
* \throw FileSystemError IO_ERROR if invalid position was given.
*/
attribute long position
setraises(FileSystemError);
/** * \brief 'Method's brief description' * * 'Method's long description' * * \api-feature 'API Feature ID' 'optional brief description' * * \code * 'example code' * \endcode * * \param 'name' - 'description' * \return 'description of the return value' * \throw 'errorobject' 'error code' if 'error condition' */
/** * \brief 'Constant's brief description' * * 'Constant's long description' * * \code * 'example code' * \endcode * */
/** * \brief 'Type's brief description' * * 'Type's long description' * * \code * 'example code' * \endcode * */