Writing documentation for the API - uyuni-project/uyuni GitHub Wiki

Writing documentation for the API methods

Table of Contents

Generating API Documentation

Uyuni API documentation is written in the source Javadoc of the API handler classes using a collection of special tags. These tags are read during the build to generate the documentation for various media such as:

  • JSP for Web UI, found in "About > API"
  • Offline plain HTML
  • Online documentation in HTML, generated from AsciiDoc output
  • PDF document, generated from Docbook output

The overall documentation is split into API namespaces. For each namespace, the documentation contains a summary description of the namespace and the list of methods in the namespace. For each method, a section contains a description of the method, the list of input parameters including the parameter names, their types, and optionally a short description of each parameter. Finally, the section describes the return type and optionally its short description.

Validating Your Changes Locally

The generated documentation is validated during the build process. To make sure your changes are valid before submitting them, apidoc-validate Ant target can be used as shown below:

$ ant -f manager-build.xml apidoc-validate

This target will build the documentation in the docbook form and run xmllint on it to validate.

Javadoc Tags

For the apidoc generator to pick up any Javadoc as the API documentation, the text must be written using a set of special tags inside the Javadoc. Below is the list of tags that are used to write the API documentation.

Tag Used in Used to write
@apidoc.namespace Handler The namespace of the handler
@apidoc.doc Handler, Method, Serializer Description of a handler or a method
@apidoc.param Method The name, type, and description of a parameter
@apidoc.returntype Method The return type and description of a method
@apidoc.ignore Handler, Method To exclude a specific handler or method from the docs

Macros

In addition to the tags listed above, the apidoc system defines a collection of macros and constants to provide a uniform format and proper styling in the generated documentation.

Most macros define a number of parameters to be filled. When using these macros, all defined macro parameters must be filled. Any parameter left out results in a broken format in the generated documentation. To offer some flexibility, some macros have multiple alternatives with different sets of parameters.

Different macros are allowed in different sections. In the listing below, the macros are grouped by the sections they're allowed in.

Parameter Macros

These macros are used to describe a single parameter of an API method. For multiple parameters, the @apidoc.param tag must be repeated for each parameter.

For every input parameter, the parameter name is mandatory and must match the actual parameter name defined in the method's Java signature. Any mismatch will prevent the API documentation readers from using the method correctly.

#param($type, $name)

#param_desc($type, $name, $desc)

These macros define a parameter of a primitive type. If the meaning of a parameter can easily be inferred from its name and therefore no description is needed, #param is used. Otherwise, #param_desc must be preferred.

Example

/**
 * @apidoc.param #param("int", "channelId")
 * @apidoc.param #param_desc("string", "label", "the desired channel label")
 /*

#array_single($type, $name)

#array_single_desc($type, $name, $desc)

These macros define a parameter of type "array of primitives". The $type parameter specifies the type of an element in the array. If the meaning of a parameter can easily be inferred from its name and therefore no description is needed, #array_single is used. Otherwise, #array_single_desc must be preferred.

Example

/**
 * @apidoc.param #array_single("int", "channelIds")
 * @apidoc.param #array_single_desc("string", "labels", "the list of desired channel labels")
 /*

#array_begin($name)

#array_begin_desc($name, $desc)

#array_end()

These macros define a parameter of type "array of objects (structs)". Unlike the other array macros, these macros must be written as open-close pairs, enclosing the definition of the type of the object (struct) elements of the array.

Since an object (struct) is a type of its own, no additional type definition is required in the enclosing macros.

Example

/**
 * @apidoc.param
 *   #array_begin("channelProperties")
 *     <struct definition goes here>
 *   #array_end()
 *
 * @apidoc.param
 *   #array_begin_desc("props", "the list of channel properties")
 *     <struct definition goes here>
 *   #array_end() 
 /*

#struct_begin($name)

#struct_desc($name, $desc)

#struct_end()

These macros define a parameter of type object (struct). They must be used as open-close pairs, enclosing the definition of the object's each property. The object properties are defined using any of the #prop macros. If the meaning of a parameter can easily be inferred from its name and therefore no description is needed, #struct_begin is used. Otherwise, #struct_desc must be preferred.

Struct macros may contain other struct macros in a nested structure.

Example

/**
 * @apidoc.param
 *   #struct_begin("systemProperties")
 *     #prop_desc("int", "sid", "the system ID")
 *     #prop_desc("string", "label", "the system label")
 *   #struct_end()
 /*

If the object definition is used as a sub-element inside an array, the parameter name is not required and the $name parameter of #struct_begin may be used to provide a short description instead.

Example

/**
 * @apidoc.param
 *   #array_begin("channelProperties")     // Parameter name in the top-level element
 *     #struct_begin("channel properties") // Description of an element of the array
 *       #prop("int", "channelId")
 *       #prop("string", "channelLabel")
 *     #struct_end()
 *   #array_end()
 /*

#prop($type, $key)

#prop_desc($type, $key, $desc)

#prop_array($key, $type, $desc)

#prop_array_begin($key)

#prop_array_begin_desc($key, $desc)

#prop_array_end()

Usable in: #struct_begin, #struct_desc

These macros define a single property of an object (struct). They must be enclosed by a #struct_begin/#struct_desc and a #struct_end macro at all times. Since object types are handled as key-value pairs in the API, all "prop" macros contain a $key parameter.

Example

/**
 * @apidoc.param
 *   #struct_begin("properties")
 *     #prop("int", "id")
 *
 *     #prop_desc("string", "label", "the channel label")
 *
 *     #prop_array("queries", "string", "the list of query words")
 *
 *     #prop_array_begin_desc("packages", "the list of packages")
 *       #struct_begin("package NEVRA")
 *         #prop_desc("string", "name", "the package name")
 *         #prop_desc("string", "evr", "the package EVR")
 *       #struct_end()
 *     #prop_array_end()
 *   #struct_end()
 /*

Return Type Macros

These macros are used to describe the return type of an API method. Unlike parameter descriptions, these macros only require a type and a short description. A parameter name is not required for return types.

#return_array_begin()

#array_end()

These macros are used to describe a return type that is an array of objects (structs) and must always used to enclose a #struct_begin #struct_end pair. Since a struct is a unique type by its own, #return_array_begin does not define a type by itself.

Example

/**
 * @apidoc.returntype
 *   #return_array_begin()
 *     #struct_begin("system details")
 *       #prop_desc("int", "sid", "the system ID")
 *       #prop("string", "hostname")
 *     #struct_end()
 *   #array_end()
 */

#array_single($type, $desc)

#struct_begin($desc)

#param($type, $desc)

When these parameter macros are used as a return type, their second parameter is used for a short description instead.

Example

/**
 * @apidoc.returntype #array_single("string", "the list of channel labels")
 */

Example

/**
 * @apidoc.returntype
 *   #struct_begin("system details")
 *     #prop_desc("int", "sid", "the system ID")
 *     #prop("string", "hostname")
 *   #struct_end()
 */

Example

/**
 * @apidoc.returntype #param("int", "the system ID")
 */

Serializer Macros

Serializers are special Java classes that serialize arbitrary data returned from the API methods into custom objects. Since every serializer outputs some object, they are documented with #struct_begin inside of a @apidoc.doc tag.

Example

/**
 * @apidoc.doc
 * #struct_begin("activation key")
 *   #prop("string", "key")
 *   #prop("string", "description")
 *   #prop("int", "usage_limit")
 * #struct_end()
 */

Other Macros

These macros provide additional styling that are complimentary to the macros listed above.

#options()

#item($item)

#item_desc($item, $desc)

#options_end()

These set of macros are used to specify a finite list of valid values for any given parameter. These macros are generally added right after a parameter macro.

Example

/**
 * @apidoc.param
 *   #param_desc("string", "contact_method", "the contact method for the system")
 *   #options()
 *     #item("default")
 *     #item("ssh-push")
 *     #item_desc("ssh-push-tunnel", "push via SSH tunnel")
 *   #options_end()
 *
 * @apidoc.param
 *   #array_single("string", "entitlements")
 *   #options()
 *     #item("container_build_host")
 *     #item("monitoring_entitled")
 *     #item("osimage_build_host")
 *     #item("virtualization_host")
 *     #item("ansible_control_node")
 *   #options_end()
 */

#session_key()

This macro is a shortcut to define the "session key" parameter that is usually the first parameter in most of the API methods. It has the same effect as writing #param("string", "sessionKey").

Example

/**
 * @apidoc.param #session_key()
 */

#return_int_success()

This macro is a shortcut to specify the common return type of int, where a successful execution would return the value 1, and any failure would throw an exception.

Example

/**
 * @apidoc.returntype #return_int_success()
 */

Constants

Additionally, the doc engine defines some constants for convenience.

$date

The $date constant can be used with any macro that expects a type parameter. The constant is resolved to dateTime.iso8601 for XMLRPC.

Example

/**
 * @apidoc.param("$date", "executionDate")
 */

$<serializerClass>

The API documentation of any serializer can be placed anywhere by placing their name following the "$" character. These constants are mostly used with the @apidoc.returntype tag.

Example

/**
 * @apidoc.returntype $SystemOverviewSerializer
 */