Documentation/DevGuide/Office Development

This chapter describes the application environment of the LibreOffice application. It assumes that you have read the chapter First Steps, and that you are able to connect to the office and load documents.

In most cases, users use the functionality of LibreOffice by opening and modifying documents. The interfaces and services common to all document types and how documents are embedded in the surrounding application environment are discussed.

It is also possible to extend the functionality of LibreOffice by replacing the services mentioned here by intercepting the communication between objects or by creating your own document type and integrating it into the desktop environment. All these things are discussed in this chapter.

LibreOffice Application Environment
The LibreOffice application environment is made up of the desktop environment and the framework API.



The desktop environment consists of the desktop service and auxiliary objects. The desktop environment's functions are carried out by the framework API. The framework API has two parts: the component framework and the dispatch framework. The component framework follows a special Frame-Controller-Model paradigm to manage components viewable in LibreOffice. The dispatch framework handles command requests sent by the GUI.

Desktop Environment
The com.sun.star.frame.Desktop service is the central management instance for the LibreOffice application framework. All LibreOffice application windows are organized in a hierarchy of frames that contain viewable components. The desktop is the root frame for this hierarchy. From the desktop you can load viewable components, access frames and components, terminate the office, traverse the frame hierarchy and dispatch command requests.

The name of this service originates at StarOffice 5.x, where all document windows were embedded into a common application window that was occupied by the StarOffice desktop, mirroring the Windows desktop. The root frame of this hierarchy was called the desktop frame. The name of this service and the interface name com.sun.star.frame.XDesktop were kept for compatibility reasons.

The desktop object and frame objects use auxiliary services, such as the com.sun.star.document.TypeDetection service and other, opaque implementations that interact with the UNO-based office, but are not accessible through the LibreOffice API. Examples for the latter are the global document event handling and its user interface, and the menu bars that use the dispatch API without being UNO services themselves. The desktop service, together with these surrounding objects, is called the desktop environment.



The viewable components managed by the desktop can be three different kinds of objects: full-blown office documents with a document model and controllers, components with a controller but no model, such as the bibliography and database browser, or simple windows without API-enabled controllers, for example, preview windows. The commonality between these types of components is the com.sun.star.lang.XComponent interface. Components with controllers are also called office components, whereas simple window components are called trivial components.

Frames in the LibreOffice API are the connecting link between windows, components and the desktop environment. The relationship between frames and components is discussed in the next section, Framework API.

Like all other services, the com.sun.star.frame.Desktop service can be exchanged by another implementation that extends the functionality of LibreOffice. By exchanging the desktop service it is possible to use different kinds of windows or to make LibreOffice use MDI instead of SDI. This is not an easy thing to do, but it is possible without changing any code elsewhere in LibreOffice.

Framework API
The framework API does not define an all-in-one framework with strongly coupled interfaces, but defines specialized frameworks that are grouped together by implementing the relevant interfaces at LibreOffice components. Each framework concentrates on a particular aspect, so that each component decides the frameworks it wants to participate in.

Currently, there are two of these frameworks: the component framework that implements the frame-controller-model paradigm and the dispatch framework that handles command requests from and to the application environment. The controller and frame implementations form the bridge between the two frameworks, because controllers and frames implement interfaces from the component framework and dispatch framework.

The framework API is an abstract specification. Its current implementation uses the Abstract Window Toolkit (AWT) specified in com.sun.star.awt, which is an abstract specification as well. The current implementation of the AWT is the Visual Component Library (VCL), a cross-platform toolkit for windows and controls written in C++ created before the specification of com.sun.star.awt and adapted to support com.sun.star.awt.

Frame-Controller-Model Paradigm in LibreOffice
The well-known Model-View-Controller (MVC) paradigm separates three application areas: document data (model), presentation (view) and interaction (controller). LibreOffice has a similar abstraction, called the Frame-Controller-Model (FCM) paradigm. The FCM paradigm shares certain aspects with MVC, but it has different purposes; therefore, it is best to approach FCM independently of MVC. The model and controller in MVC and FCM are quite different things.

The FCM paradigm in LibreOffice separates three application areas: document object (model), screen interaction with the model (controller) and controller-window linkage (frame).


 * The model holds the document data and has methods to change these data without using a controller object. Text, drawings, and spreadsheet cells are accessed directly at the model.
 * The controller has knowledge about the current view status of the document and manipulates the screen presentation of the document, but not the document data. It observes changes made to the model, and can be duplicated to have multiple controllers for the same model.
 * The frame contains the controller for a model and knows the windows that are used with it, but does not have window functionality.

The purpose of FCM is to have three exchangeable parts that are used with an exchangeable window system:

It is possible to write a new controller that presents an existing model differently without changing the model or the frame. A controller depends on the model it presents; therefore, a new controller for a new model can be written.

Developers can introduce new models for new document types without taking care of the frame and underlying window management system. However, since there is no default controller, it is necessary to write a suitable controller also.

By keeping all window-related functionality separate from the frame, it is possible to use one single frame implementation for every possible window in the entire LibreOffice application. Thus, the presentation of all visible components is customized by exchanging the frame implementation. At runtime you can access a frame and replace the controller, together with the model it controls, by a different controller instance.

Linking Components and Windows
The main role of a frame in the Frame-Controller-Model paradigm is to act as a liaison between viewable components and the window system.

Frames can hold one component, or a component and one or more subframes. The following two illustrations depict both possibilities. The first illustration shows a frame containing only a component. It is connected with two window instances: the container window and component window.



When a frame is constructed, the frame must be initialized with a container window using com.sun.star.frame.XFrame:initialize. This method expects the com.sun.star.awt.XWindow interface of a surrounding window instance, which becomes the container window of the frame. The window instance passed to  must also support com.sun.star.awt.XTopWindow to become a container window. The container window must broadcast window events, such as, and appear in front of other windows or be sent to the background. The fact that container windows support com.sun.star.awt.XTopWindow does not mean the container window is an independent window of the underlying window system with a title bar and a system menu. An  acts as a window if necessary, but it can also be docked or depend on a surrounding application window.

After initializing the frame, a component is set into the frame by a frame loader implementation that loads a component into the frame. It calls com.sun.star.frame.XFrame:setComponent that takes another com.sun.star.awt.XWindow instance and the com.sun.star.frame.XController interface of a controller.Usually the controller is holding a model, therefore the component gets a component window of its own, separate from the container window.

A frame with a component is associated with two windows: the container window which is an  and the component window, which is the rectangular area that displays the component and receives GUI events for the component while it is active. When a frame is initialized with an instance of a window in a call to, this window becomes its container window. When a component is set into a frame using, another com.sun.star.awt.XWindow instance is passed and becomes the component window.

When a frame is added to the desktop frame hierarchy, the desktop becomes the parent frame of our frame. For this purpose, the com.sun.star.frame.XFramesSupplier interface of the desktop is passed to the method  at the   interface. This happens internally when the method  is called at the com.sun.star.frame.XFrames interface supplied by the desktop.

The second diagram shows a frame with a component and a sub-frame with another component. Each frame has a container window and component window.



In the LibreOffice GUI, sub-frames appear as dependent windows. The sub-frame in the illustration above could be a dockable window, such as the beamer showing the database browser or a floating frame in a document created with.

Note that a frame with a component and sub-frame is associated with four windows. The frame and the sub-frame have a container window and a component window for the component.

When a sub-frame is added to a surrounding frame, the frame becomes the parent of the sub-frame by a call to  at the sub-frame. This happens internally when the method  is called at the com.sun.star.frame.XFrames interface supplied by the surrounding frame.

The section Creating Frames Manually shows examples for the usage of the  interface that creates frames in the desktop environment, constructs dockable and standalone windows, and inserts components into frames.

Communication through Dispatch Framework
Besides the main role of frames as expressed in the com.sun.star.frame.XFrame interface, frames play another role by providing a communication context for the component they contain, that is, every communication from a controller to the desktop environment and the user interface, and conversely, is done through the frame. This aspect of a frame is published through the com.sun.star.frame.XDispatchProvider interface, which uses special command requests to trigger actions.

The section Using the Dispatch Framework discusses the usage of the dispatch API.

Components in Frames
The desktop environment section discussed the three kinds of viewable components that can be inserted into a frame. If the component has a controller and a model like a document, or if it has only a controller, such as the bibliography and database browser, it implements the com.sun.star.frame.Controller service represented by the interface com.sun.star.frame.XController. In the call to com.sun.star.frame.XFrame:setComponent, the controller is passed with the component window instance. If the component has no controller, it directly implements com.sun.star.lang.XComponent and com.sun.star.awt.XWindow. In this case, the component is passed as  parameter, and the   parameter must be a   reference set to null.

If the viewable component is a trivial component (implementing  only), the frame holds a reference to the component window, controls the lifetime of the component and propagates certain events from the container window to the component window. If the viewable component is an office component (having a controller), the frame adds to these basic functions a set of features for integration of the component into the environment by supporting additional command URLs for the component at its com.sun.star.frame.XDispatchProvider interface.

Controllers
Controllers in LibreOffice are between a frame and document model. This is their basic role as expressed in com.sun.star.frame.XController, which has methods  and. The method  provides the frame that the controller is attached to. The method  returns a document model, but it may return an empty reference if the component does not have a model.

Usually the controller objects support additional interfaces specific to the document type they control, such as com.sun.star.sheet.XSpreadsheetView for Calc document controllers or com.sun.star.text.XTextViewCursorSupplier for Writer document controllers.



A single document model can be controlled simultaneously by several controller instances, each associated with a separate frame. Multiple controllers and frames are created by LibreOffice when the user clicks.

Windows
Windows in the LibreOffice API are rectangular areas that are positioned and resized, and inform listeners about UI events ( com.sun.star.awt.XWindow ). They have a platform-specific counterpart that is wrapped in the com.sun.star.awt.XWindowPeer interface, which is invalidated (redrawn), and sets the system pointer and hands out the toolkit for the window. The usage of the window interfaces is outlined in the section Window Interfaces below.

Dispatch Framework
The dispatch framework is designed to provide uniform access to components for a GUI by using command URLs that mirror menu items, such as, with various document components. Only the component knows how to execute a command. Similarly, different document components trigger changes in the UI by common commands. For example, a controller might create UI elements like a menu bar, or open a hyperlink.

Command dispatching follows a chain of responsibility. Calls to the dispatch API are moderated by the frame, so all dispatch API calls from the UI to the component and conversely are handled by the frame. The frame passes on the command until an object is found that can handle it. It is possible to restrict, extend or redirect commands at the frame through a different frame implementation or through other components connecting to the frame.

It has already been discussed that frames and controllers have an interface com.sun.star.frame.XDispatchProvider. The interface is used to query a dispatch object for a command URL from a frame and have the dispatch object execute the command. This interface is one element of the dispatch framework.

By offering the interception of dispatches through the interface com.sun.star.frame.XDispatchProviderInterception, the Frame service offers a method to modify a component's handling of GUI events while keeping its whole API available simultaneously.

The usage of the Dispatch Framework is described in the section Using the Dispatch Framework.

Using the Desktop


The com.sun.star.frame.Desktop service available at the global service manager includes the service com.sun.star.frame.Frame. The Desktop service specification provides three interfaces: com.sun.star.frame.XDesktop, com.sun.star.frame.XComponentLoader and com.sun.star.document.XEventBroadcaster , as shown in the following UML chart:



The interface com.sun.star.frame.XDesktop provides access to frames and components, and controls the termination of the office process. It defines the following methods:

The methods  and   distribute the active frame and document model, whereas   returns a com.sun.star.container.XEnumerationAccess to all loaded documents. For documents loaded in the desktop environment the methods  and   always return the com.sun.star.lang.XComponent interface of the document model.

The office process is usually terminated when the user selects or after the last application window has been closed. Clients can terminate the office through a call to  and add a terminate listener to veto the shutdown process.

As long as the Windows quickstarter is active, the soffice executable is not terminated.

The following sample shows an com.sun.star.frame.XTerminateListener implementation that prevents the office from being terminated when the class  is still active:

The following class  tests the   above.

The office freezes when  is called if there are unsaved changes. As a workaround set all documents into an unmodified state through their com.sun.star.util.XModifiable interface or store them using com.sun.star.frame.XStorable.

The Desktop offers a facility to load components through its interface com.sun.star.frame.XComponentLoader. It has one method:

Refer to chapter Handling Documents for details about the loading process.

For versions beyond 641, the desktop also provides an interface that allows listeners to be notified about certain document events through its interface com.sun.star.document.XEventBroadcaster.

The  must implement a single method (besides  ):

The struct com.sun.star.document.EventObject has a  member   that assumes one of the values specified in com.sun.star.document.Events. The corresponding events are found on the Events tab of the Tools - Configure dialog when the option OpenOffice is selected.

The desktop broadcasts these events for all loaded documents.

The current version of LibreOffice does not have a GUI element as a desktop. The redesign of the LibreOffice GUI in StarOffice 5.x and later resulted in the com.sun.star.frame.Frame service part of the desktop service is now non-functional. While the  interface can still be queried from the desktop, almost all of its methods are dummy implementations. The default implementation of the desktop object in LibreOffice is not able to contain a component and refuses to be attached to it, because the desktop is still a frame that is the root for the common hierarchy of all frames in LibreOffice. The desktop has to be a frame because its com.sun.star.frame.XFramesSupplier interface must be passed to com.sun.star.frame.XFrame:setCreator at the child frames, therefore the desktop becomes the parent frame. However, the following functionality of com.sun.star.frame.Frame is still in place:

The desktop interface com.sun.star.frame.XFramesSupplier offers methods to access frames. This interface inherits from com.sun.star.frame.XFrame, and introduces the following methods:

The method  returns a com.sun.star.frame.XFrames container, that is a com.sun.star.container.XIndexAccess, with additional methods to add and remove frames:

This  collection is used when frames are added to the desktop to become application windows.

Through, you access the active sub-frame of the desktop frame, whereas   is called by a sub-frame to inform the desktop about the active sub-frame.

The object returned by  does not support , therefore it cannot be used with LibreOffice Basic.

The parent interface of, com.sun.star.frame.XFrame is functional by accessing the frame hierarchy below the desktop. These methods are discussed in the section Frames below:

The generic dispatch interface com.sun.star.frame.XDispatchProvider executes functions of the internal  implementation that are not accessible through specialized interfaces. Dispatch functions are described by a command URL. The  returns a dispatch object that dispatches a given command URL. A reference of command URLs supported by the desktop is available on LibreOffice (OpenOffice.org_3.x_Commands). Through the com.sun.star.frame.XDispatchProviderInterception, client code intercepts the command dispatches at the desktop. The dispatching process is described in section Using the Dispatch Framework.

Using the Component Framework
The component framework comprises the interfaces of frames, controllers and models used to manage components in the LibreOffice desktop environment. In our context, everything that "dwells" in a frame of the desktop environment is called a component, because the interface com.sun.star.lang.XComponent is the common denominator for objects that are loaded into frames.

Frames, controllers and models hold references to each other. The frame is by definition the default owner of the controller and the model, that is, it is responsible to call dispose on the controller and model when it is destroyed itself. Other objects that are to hold references to the frame, controller, or model must register as listeners to be informed when these references become invalid. Therefore,   and   inherit from  :

The process to resolve the circular dependencies of the component framework is complex. For instance, the objects involved in the process may be in a condition where they may not be disposed of. Refer to the section Closing Documents for additional details.

Theoretically every UNO object could exist in a frame, as long as it is willing to let the frame control its existence when it ends.

A trivial component ( only) is enough for simple viewing purposes, where no activation of a component and related actions like cursor positioning or user interactions are necessary.

If the component participates in more complex interactions, it must implement the controller service.

Many features of the desktop environment are only available if the URL of a component is known. For example:


 * Presenting the URL or title of the document.
 * Inserting the document into the autosave queue.
 * Preventing the desktop environment from loading documents twice.
 * Allow for participation in the global document event handling.

In this case, com.sun.star.frame.XModel comes into operation, since it has methods to handle URLs, among others.

So a complete office component is made up of


 * a controller object that presents the model or shows a view to the model that implements the com.sun.star.frame.Controller service, but publishes additional document-specific interfaces. For almost all LibreOffice document types there are document specific controller object specifications,such as com.sun.star.sheet.SpreadsheetView, and com.sun.star.drawing.DrawingDocumentDrawView . For controllers, refer to the section Controllers.
 * a model object implementing the com.sun.star.document.OfficeDocument service. Refer to the section Models.

Getting Frames, Controllers and Models from Each Other
Usually developers require the controller and frame of an already loaded document model. The com.sun.star.frame.XModel interface of LibreOffice document models gets the controller that provides access to the frame through its com.sun.star.frame.XController interface. The following illustration shows the methods that get the controller and frame for a document model and conversely. From the frame, obtain the corresponding component and container window.



If the loaded component is a trivial component and implements com.sun.star.awt.XWindow only, the window and the window peer is reached by querying these interfaces from the com.sun.star.lang.XComponent returned by.

Frame Setup
The main role of a frame is to link components into a surrounding window system. This role is expressed by the following methods of the frame's main interface com.sun.star.frame.XFrame :

The first two methods deal with the container window of a frame, the latter three are about linking the component and the component window with the frame. The method initialize expects a top window that is created by the AWT toolkit that becomes the container window of the frame and is retrieved by.

Frame Hierarchies
When frames link components into a surrounding window system, they build a frame hierarchy. This aspect is covered by the hierarchy-related  methods:

The  method   informs a frame about its parent frame and must be called by a frames container ( com.sun.star.frame.XFrames ) when a frame is added to it by a call to com.sun.star.frame.XFrames:append. A frames container is provided by frames supporting the interface com.sun.star.frame.XFramesSupplier. is currently supported by the desktop frame and by the default frame implementation used by LibreOffice documents. It is described below.

The frame has a custom name that is read through  and written through. Frames in the desktop hierarchy created by GUI interaction usually do not have names. The  returns an empty string for them, whereas frames that are created for special purposes, such as the beamer frame or the online help, have names. Developers can set a name and use it to address a frame in  calls or when loading a component into the frame. Custom frame names must not start with an underscore. Leading underscores are reserved for special frame names. See below.

Every frame in the frame hierarchy is accessed through any other frame in this hierarchy by calling the  method. This method searches for a frame with a given name in five steps: self, children, siblings, parent, and create if not found. The  checks the called frame, then calls   at its children, then its siblings and at its parent frame. The fifth step in the search strategy is reached if the search makes it to the desktop without finding a frame with the given name. In this case, a new frame is created and assigned the name that was searched for. If the top frame is outside the desktop hierarchy, a new frame is not created.

The name used with  can be an arbitrary string without a leading underscore or one of the following reserved frame names. These names are for internal use for loading documents. Some of the reserved names are logical in a  call, also. A complete list of reserved frame names can be found in section Target Frame.


 * _top
 * Returns the top frame of the called frame, first frame where isTop returns true when traveling up the hierarchy.


 * _parent
 * Returns the next frame above in the frame hierarchy.


 * _self
 * Returns the frame itself, same as an empty target frame name. This means you are searching for a frame you already have, but it is legal to do so.


 * _blank
 * Creates a new top-level frame whose parent is the desktop frame.

Calls with " " or " " return the frame itself if the called frame is a top frame or has no parent. This is compatible to the targeting strategies of web browsers.

We have seen that  is called recursively. To control the recursion, the search flags parameter specified in the constants group com.sun.star.frame.FrameSearchFlag is used. For all of the five steps mentioned above, a suitable flag exists. Every search step can be prohibited by deleting the appropriate. The search flag parameter can also be used to avoid ambiguities caused by multiple occurrences of a frame name in a hierarchy by excluding parts of the frame tree from the search. If  is called for a reserved frame name, the search flags are ignored.

There are separate frame hierarchies that do not interact with each other. If a frame is created, but not inserted into any hierarchy, it becomes the top frame of its own hierarchy. This frame and its contents can not be accessed from other hierarchies by traversing the frame hierarchies through API calls. Also, this frame and its content cannot reach frames and their contents in other hierarchies. It is the code that creates a frame and decides if the new frame becomes part of an existing hierarchy, thus enabling it to find other frames, and making it and its viewable component visible to the other frames. Examples for frames that are not inserted into an existing hierarchy are preview frames in dialogs, such as the document preview in the and Documents dialog.

Frame Actions
Several actions take place at a frame. The context of viewable components can change, a frame may be activated or the relationship between frame and component may be altered. For instance, when the current selection in a document has been changed, the controller informs the frame about it by calling. The frame then tells its frame action listeners that the context has changed. The frame action listeners are also informed about changes in the relationship between the frame and component, and about frame activation. The corresponding  methods are:

The method  makes the given frame the active frame in its parent container. If the parent is the desktop frame, this makes the associated component the current component. However, this is not reflected in the user interface by making the corresponding window the top window. If the container of the active frame is to be the top window, use  at the com.sun.star.awt.XWindow interface of the container window.

The interface com.sun.star. frame.XFrameActionListener used with  must implement the following method:

XFramesSupplier
The  interface com.sun.star.frame.XFramesSupplier offers methods to access sub-frames of a frame. The frame implementation of LibreOffice supports this interface. This interface inherits from com.sun.star.frame.XFrame, and introduces the following methods:

The method  returns a com.sun.star.frame.XFrames container, that is a com.sun.star.container.XIndexAccess with additional methods to add and remove frames:

This  collection is used when frames are appended to a frame to become sub-frames. The  method implementation must extend the existing frame hierarchy by an internal call to   at the parent frame in the frame hierarchy. The parent frame is always the frame whose  interface is used to append a new frame.

Through  access the active sub-frame in a frame with subframes. If there are no sub-frames or a sub-frame is currently non-active, the active frame is. The  is called by a sub-frame to inform the frame about the activation of the sub-frame. In, the method   at the creator is called, then the registered frame action listeners are notified by an appropriate call to   with com.sun.star.frame.FrameActionEvent:Action set to.

XDispatchProvider and XDispatchProviderInterception
Frame services also support com.sun.star.frame.XDispatchProvider and com.sun.star.frame.XDispatchProviderInterception. The section Using the Dispatch Framework explains how these interfaces are used.

XStatusIndicatorFactory
The frame implementation supplies a status indicator through its interface com.sun.star.task.XStatusIndicatorFactory. A status indicator can be used by a frame loader to show the loading process for a document. The factory has only one method that returns an object supporting com.sun.star.task.XStatusIndicator :

The status indicator is displayed by a call to com.sun.star.task.XStatusIndicator:start. Pass a text and a numeric range, and use  to let the status bar grow until the maximum range is reached. The method  removes the status indicator.

XController
A com.sun.star.frame.XController inherits from com.sun.star.lang.XComponent and introduces the following methods:

The com.sun.star.frame.XController links model and frame through the methods  and. These methods and the corresponding methods in the com.sun.star.frame.XModel and com.sun.star.frame.XFrame interfaces act together. Calling  at the controller must be accompanied by a corresponding call of   at the model, and   at the controller must have its counterpart   at the frame.

The controller is asked for permission to dispose of the entire associated component by using. The  method shows dialogs, for example, to save changes. To avoid the dialog, close the corresponding frame without using  before. The section Closing Documents provides additional information.

Developers retrieve and restore data used to setup the view at the controller by calling. These methods are usually called on loading and saving the document, but they also allow developers to manipulate the state of a view from the outside. The exact content of this data depends on the concrete controller/model pair.

XDispatchProvider
Through com.sun.star.frame.XDispatchProvider, the controller participates in the dispatch framework. It is described in section Using the Dispatch Framework.

XSelectionSupplier
The optional  interface com.sun.star.view.XSelectionSupplier accesses the selected object and informs listeners when the selection changes:

The type of selection depends on the type of the document and the selected object. It is also possible to get the current selection in the active or last controller of a model by calling the method  in the com.sun.star.frame.XModel interface.

XContextMenuInterception
The optional  interface com.sun.star.ui.XContextMenuInterception intercepts requests for context menus in the document's window. See chapter Intercepting Context Menus.

Document Specific Controller Services
The com.sun.star.frame.Controller specification is generic and does not describe additional features required for a fully functional document controller specification, such as the controller specifications for Writer, Calc and Draw documents. The following table shows the controller services specified for LibreOffice document components.

Once the reference to a controller is retrieved, you can query for these interfaces. Use the com.sun.star.lang.XServiceInfo interface of the model to ask it for the supported service(s). The component implementations in LibreOffice support the following services. Refer to the related chapters for additional information about the interfaces you get from the controllers of LibreOffice documents.

Models
There is not an independent specification for a model service. The interface com.sun.star.frame.XModel is currently supported by Writer, Calc, Draw and Impress document components. In our context, we call objects supporting com.sun.star.frame.XModel, model objects. All LibreOffice document components have the service com.sun.star.document.OfficeDocument in common. An  implements the following interfaces:

XModel
The interface com.sun.star.frame.XModel inherits from com.sun.star.lang.XComponent and introduces the following methods, which handle the model's resource description, manage its controllers and retrieves the current selection.

The method  provides the URL where a document was loaded from or last stored using. As long as a new document has not been saved, the URL is an empty string. The method  returns a sequence of property values that report the resource description according to com.sun.star.document.MediaDescriptor, specified on loading or saving with s. The method  is used by the frame loader implementations to inform the model about its URL and.

The current or last active controller for a model is retrieved through. The corresponding method  sets a different current controller at models where additional controllers are available. However, additional controllers can not be created at this time for LibreOffice components using the component API. The method  is used by frame loader implementations and provides the model with a new controller that has been created for it, without making it the current controller. The  tells the model that a controller may no longer be used. Finally, the model holds back screen updates using  and. For each call to, there must be a call to   to remove the lock. The method  tells if the controllers are locked.

The currently selected object is retrieved by a call to. This method is an alternative to  at the com.sun.star.view.XSelectionSupplier interface supported by controller services.

XModifiable
The interface com.sun.star.util.XModifiable traces the modified status of a document:

XStorable
The interface com.sun.star.frame.XStorable stores a document under an arbitrary URL or its current location. Details about how to use this interface are discussed in the chapter Handling Documents.

XPrintable
The interface com.sun.star.view.XPrintable is used to set and get the printer and its settings, and dispatch print jobs. These methods and special printing features for the various document types are described in the chapters Printing Text Documents, Printing Spreadsheet Documents, Printing Drawing Documents and Printing Presentation Documents.

XEventBroadcaster
For versions later than 641, the optional interface com.sun.star.document.XEventBroadcaster at office documents enables developers to add listeners for events related to office documents in general, or for events specific for the individual document type.See Document Events).

The  must implement a single method, besides  :

The struct com.sun.star.document.EventObject has a string member, that assumes one of the values specified in com.sun.star.document.Events. These events are also on the Events tab of the dialog.

The general events are the same events as those provided at the  interface of the desktop. While the model is only concerned about its own events, the desktop broadcasts the events for all the loaded documents.

XEventsSupplier
The optional interface com.sun.star.document.XEventsSupplier binds the execution of dispatch URLs to document events, thus providing a configurable event listener as a simplification for the more general event broadcaster or listener mechanism of the com.sun.star.document.XEventBroadcaster interface. This is done programmatically versus manually in.

XDocumentPropertiesSupplier
The optional interface com.sun.star.document.XDocumentPropertiesSupplier provides access to document information as described in section Document Info. Document information is presented in the dialog in the GUI.

XViewDataSupplier
The optional com.sun.star.document.XViewDataSupplier interface sets and restores view data.

The view data are a com.sun.star.container.XIndexAccess to sequences of com.sun.star.beans.PropertyValue structs. Each sequence represents the settings of a view to the model that supplies the view data.

Document Specific Features
Every service specification for real model objects provides more interfaces that constitute the actual model functionality For example, a text document service com.sun.star.text.TextDocument provides text related interfaces. Having received a reference to a model, developers query for these interfaces. The com.sun.star.lang.XServiceInfo interface of a model can be used to ask for supported services. The LibreOffice document types support the following services:

Refer to the related chapters for additional information about the interfaces of the documents of LibreOffice.

Window Interfaces
The window interfaces of the component window and container window control the LibreOffice application windows. This chapter provides a short overview.

XWindow
The interface com.sun.star.awt.XWindow is supported by the component and controller windows. This interface comprises methods to resize a window, control its visibility, enable and disable it, and make it the focus for input device events. Listeners are informed about window events.

The com.sun.star.awt.XWindowListener gets the following notifications. The com.sun.star.awt.WindowEvent has members describing the size and position of the window.

What the other listeners do are evident by their names.

XTopWindow
The interface com.sun.star.awt.XTopWindow is available at container windows. It informs listeners about top window events, and it can put itself in front of other windows or withdraw into the background. It also has a method to control the current menu bar:

The top window listener receives the following messages. All methods take a com.sun.star.lang.EventObject.

XWindowPeer
Each  has a com.sun.star.awt.XWindowPeer. The com.sun.star.awt.XWindowPeer interface accesses the window toolkit implementation used to create it and provides the pointer of the pointing device, and controls the background color. It is also used to invalidate a window or portions of it to trigger a redraw cycle.

Frame Creation
Every time a frame is needed in LibreOffice, the com.sun.star.frame.Frame service is created. LibreOffice has an implementation for this service, available at the global service manager.

This service can be replaced by a different implementation, for example, your own implementation in Java, by registering it at the service manager. In special cases, it is possible to use a custom frame implementation instead of the com.sun.star.frame.Frame service by instantiating a specific implementation using the implementation name with the factory methods of the service manager. Both methods can alter the default window and document handling in LibreOffice, thus changing or extending its functionality.

Assigning Windows to Frames
Every frame can be assigned to any LibreOffice window. For instance, the same frame implementation is used to load a component into an application window of the underlying windowing system or into a preview window of a LibreOffice dialog. The com.sun.star.frame.Frame service implementation does not depend on the type of the window, although the entirety of the frame and window will be a different object by the user.

If you have a window in your application and want to load a LibreOffice document, create a frame and window object, and put them together by a call to. A default frame is created by instantiating an object implementing the com.sun.star.frame.Frame service at the global service manager. For window creation, the current com.sun.star.awt implementation has to be used to create windows in all languages supporting UNO. This toolkit offers a method to create window objects that wrap a platform specific window, such as a Java AWT window or a Windows system window represented by its window handle. A Java example is given below.

Two conditions apply to windows that are to be used with LibreOffice frames.

The first condition is that the window must be created by the current com.sun.star.awt.Toolkit service implementation. Not every object implementing the com.sun.star.awt.XWindow interface is used as an argument in the  method, because it is syntactically correct, but it is restricted to objects created by the current com.sun.star.awt implementation. The insertion of a component into a frame only works if all involved windows are .xbl created by the same toolkit implementation. All internal office components, such as Writer and Calc, are implemented using the Visual Component Library (VCL), so that they do not work if the container window is not implemented by VCL. The current toolkit uses this library internally, so all the windows created by the awt toolkit are passed to a frame. No others work at this time. Using VCL directly is not recommended. The code has to be rewritten, whenever this complication has incurred by the current office implementation and is removed, and the toolkit implementation is exchangeable.

The second condition is that if a frame and its component are supposed to get  messages, the window object implements the additional interface com.sun.star.awt.XTopWindow. This is necessary for editing components, because the  event shows a cursor or a selection in the document. As long as this condition is met, further code is not necessary for the interaction between the frame and window, because the frame gets all the necessary events from the window by registering the appropriate listeners in the call to.

When you use the com.sun.star.awt.Toolkit to create windows, supply a com.sun.star.awt.WindowDescriptor struct to describe what kind of window is required. Set the  member of this struct to com.sun.star.awt.WindowClass:TOP and the   member to " " if you want to have an application window, or to " " if a window is need to be inserted in other windows created by the toolkit.

Setting Components into Frame Hierarchies
Once a frame has been initialized with a window, it can be added to a frames supplier, such as the desktop using the frames container provided by com.sun.star.frame.XFramesSupplier:getFrames. Its method com.sun.star.frame.XFrames:append inserts the new frame into the XFrames container and calls   at the new frame, passing the   interface of the parent frame.

The following example creates a new window and a frame, plugs them together, and adds them to the desktop, thus creating a new, empty LibreOffice application window.

Loading Documents
The framework API defines a simple but powerful interface to load viewable components, the com.sun.star.frame.XComponentLoader. This interface is implemented by the globally accessible com.sun.star.frame.Desktop service and also by the com.sun.star.frame.Frame service.



The interface com.sun.star.frame.XComponentLoader has one method:

In the following sections the arguments of this call are explained. For a more detailed description of what happens when this call is executed, see the chapter about the filtering process. It explains how the various parameters in the  allow to detect the type of the file to load, the best filter to load it and the document type that will receive the data. If these parameters were known already and a document should be loaded without becoming attached to a frame, a simple way to load a document exists that bypasses the detection step and the frame creation:


 * create the document by instantiating it with its UNO service name
 * get the com.sun.star.frame.XLoadable interface from the document
 * call its com.sun.star.frame.XLoadable:load (…) method that gets the MediaDescriptor as parameter

MediaDescriptor
A call to  receives a sequence of com.sun.star.beans.PropertyValue structs as a parameter, which implements the com.sun.star.document.MediaDescriptor service, consisting of property definitions. In general it describes a resource and how it shall be handled in the particular context where the  is used. In the context of loading a file it describes the "from where" and the "how". In the content of storing a document using the interface com.sun.star.frame.XStorable it describes the "where to" and the "how". The table below shows the properties defined in the media descriptor.

Some properties are used for loading and saving while others apply to one or the other. If a media descriptor is used, only a few of the members are specified. The others assume default values. Strings default to empty strings in general and interface references default to empty references. For all other properties, the default values are specified in the description column of the table.

Some properties are tagged deprecated. There are old implementations that still use these properties. They are supported, but their use is discouraged. Use the new property that can be found in the description column of the deprecated property.

To develop a UNO component that uses the media descriptor, note that all the properties are under control of the framework API. Never create your own property names for the media descriptor, or name clashes may be induced if the framework in a later version defines a property that uses the same name. Instead, use the  property to transport document specific information. is specified to be an, therefore it can be a sequence of property values by itself. If you do use it. make an appropriate specification available to users of your component.

The media descriptor used for loading and storing components is passed as an in/out parameter to some methods of objects that participate in the loading or storing process, e.g. the com.sun.star.document.TypeDetection service or a com.sun.star.document.ExtendedTypeDetection service, but also to the filter objcects involved. This enable these objects to add more information to the MediaDescriptor. As an example, if the MediaDescriptor at the beginning just contains a URL. If an object uses this URL to open a stream, it should add this stream to the MediaDescriptor (Stream, InputStream or OutputStream). This prevents that other objects have to create the stream a second time (unfortunate if a remote file is loaded) and it must be reused by later users of the MediaDescriptor.

So if a method gets a MediaDescriptor parameter for loading content it is supposed to do the following:


 * first check for a "Stream" property
 * if it isn't available, check for an "InputStream" property
 * if you find a stream, don't expect that its position is at the beginning of the file, seek to the position where you want to start
 * only if none of these properties is available, try to create a stream by yourself from other properties, e.g. the URL property
 * if the resulting stream is seekable (supports com.sun.star.io.XSeekable, add it to the MediaDescriptor if it is an in/out parameter
 * if the resulting stream is seekable, the MediaDescriptor is an in-parameter and the stream isn't a return value, close it when you are done with it
 * if the stream is not seekable, it is a "one way read" stream and must not be added to the MediaDescriptor.

If it gets a MediaDescriptor parameter for storing content the workflow is:
 * first check for a "Stream" property
 * if it isn't available, check for an "OutputStream" property
 * only if none of these properties is available, try to create a stream by yourself from other properties, e.g. the URL property
 * if the resulting stream is seekable, it can be used for a direct access
 * if the resulting stream isn't seekable, a temporary stream must be created for the storing process and after successful storing all content must be copied to the target stream.

Methods that get the MediaDescriptor as in-parameter only of course can't modify it.

URL Parameter
The URL is part of the media descriptor and also an explicit parameter for. This enables script code to load a document without creating a media descriptor at the cost of code redundancy. The URL parameter of  overrides a possible URL property passed in the media descriptor. Aside from valid URLs that describe an existing file, the following URLs are used to open viewable components in LibreOffice:

Such empty documents also can created without a frame:


 * create the document by instantiating it with its UNO service name
 * get the com.sun.star.frame.XLoadable interface from the document
 * call its initNew method.

Target Frame
The URL and media descriptor  have two additional arguments, the target frame name and search flags. The method  looks for a frame in the frame hierarchy and loads the component into the frame it finds. It uses the same algorithm as  at the com.sun.star.frame.XFrame interface, described in section Frame Hierarchies.

The target frame name is a reserved name starting with an underscore or arbitrary name. The reserved names denote frequently used frames in the frame hierarchy or special functions, whereas an arbitrary name is searched recursively. If a reserved name is used, the search flags are ignored and set to 0. The following reserved names are supported:


 * _self
 * Returns the frame itself. The same as with an empty target frame name. This means to search for a frame you already have, but it is legal.


 * _top
 * Returns the top frame of the called frame .,The first frame where  returns true when traveling up the hierarchy. If the starting frame does not have a parent frame, the call is treated as a search for " ". This behavior is compatible to the frame targeting in a web browser.


 * _parent
 * Returns the next frame above in the frame hierarchy. If the starting frame does not have a parent frame, the call is treated as a search for " ". This behavior is compatible to the frame targeting in a web browser.


 * _blank
 * Creates a new top-level frame as a child frame of the desktop. If the called frame is not part of the desktop hierarchy, this call fails. Using the " " target loads open documents again that result in a read-only document, depending on the UCB content provider for the component. If loading is done as a result of a user action, this becomes confusing to the users, therefore the " " target is recommended in calls from a user interface, instead of " ". Refer to the next section for a discussion about the _default target.


 * _default
 * Similar to " ", but the implementation defines further behavior that has to be documented by the implementer. The com.sun.star.frame.XComponentLoader implemented at the desktop object shows the following default behavior.


 * First, it checks if the component to load is already loaded in another top-level frame. If this is the case, the frame is activated and brought to the foreground. When the  property is set to true in the media descriptor, the loader creates a second controller to show another view for the loaded document. For components supporting this, a second window is opened as if the user clicked Window - New Window. The other components are loaded one more time, as if the " " target had been used. Currently, almost all office components implementing com.sun.star.frame.XModel have multiple controllers, except for HTML and writer documents in the online view. The database and bibliography components have no model, therefore they cannot open a second view at all and   leads to an exception with them.


 * Next, the loader checks if the active frame contains an unmodified, empty document of the same document type as the component that is being loaded. If so, the component is loaded into that frame, replacing the empty document, otherwise a new top-level frame is created similar to a call with " ".

Names starting with an underscore must not be used as real names for a frame.

If the given frame name is an arbitrary string, the loader searches for this frame in the frame hierarchy. The search is done in the following order: self, children, siblings, parent, create if not found. Each of these search steps can be skipped by deleting it from the com.sun.star.frame.FrameSearchFlag bit vector:

A typical case for a named frame is a situation where a frame is needed to be reused for subsequent loading of components, for example, a frame attached to a preview window or a docked frame, such as the frame in LibreOffice that opens the address book when the F4 key is pressed.

The frame names " ", " " and " " define a frame target relative to a starting frame. They can only be used if the component loader interface finds the frame and the  can be used with the frame. The desktop frame is the root, therefore it does not have a top and parent frame. The component loader of the desktop cannot use these names, because the desktop refuses to have a component set into it. However, if a frame implemented com.sun.star.frame.XComponentLoader, these names could be used.

The reserved frame names are also used as a targeting mechanism in the dispatch framework with regard to as far as the relative frame names being resolved. For additional information, see chapter Using the Dispatch Framework.

The example below creates a frame, and uses the target frame and search flag parameters of  to load a document into it.

The  call returns a reference to a com.sun.star.lang.XComponent interface. The object belonging to this interface depends on the loaded component. If it is a component that only provides a component window, but not a controller, the returned component is this window. If it is an office component that provides a controller, the returned component is the controller or its model, if these is one. All Writer, Calc, Draw, Impress or Math documents in LibreOffice support a model, therefore the  call returns it. The database and bibliography components however, return a controller, because they do not have a model.

Closing Documents
The com.sun.star.frame.XComponentLoader:loadComponentFromURL has previously been discussed. The return value is a reference to a com.sun.star.lang.XComponent interface, the corresponding object is a disposable component, and the caller must take care of its lifetime. An  supports the following methods:

In principle, there is a simple rule. The documentation of a com.sun.star.lang.XComponent specifies the objects that can own a component. Normally, a client using an  is the owner of the   and has the responsibility to dispose of it or it is not the owner. If it is not the owner, it may add itself as a com.sun.star.lang.XEventListener at the  and not call   on it. This type of  supports one method in which a component reacts upon the fact that another component is about to be disposed of:

However, the frame, controller and model are interwoven tightly, and situations do occur in which there are several owners, for example, if there is more than one view for one model, or one of these components is in use and cannot be disposed of, for example, while a print job is running or a modal dialog is open. Therefore, developers must cope with these situations and remember a few things concerning the deletion of components.

Closing a document has two aspects. It is possible that someone else wants to close a document being currently worked on And you may want to close a component someone else is using at the same time. Both aspects are discussed in the following sections. A code example that closes a document is provided at the end of this section.

Reacting Upon Closing
The first aspect is that someone else wants to close a component for which you hold a reference. In the current version of LibreOffice, there are three possibilities.


 * If the component is used briefly as a stack variable, you do not care about the component after loading, or you are sure there will be no interference, it is justifiable to load the component without taking further measures. If the user is going to close the component, let the reference go out of scope, or release the reference when no longer required.
 * If a reference is used, but it is not necessary to react when it becomes invalid and the object supports com.sun.star.uno.XWeak, you can hold a weak reference instead of a hard reference. Weak references are automatically converted to null if the object they reference is going to be disposed. Because the generic frame implementation, and also the controllers and models of all standard document types implement , it is recommended to use it when possible.
 * If a hard reference is held or you want to know that the component has been closed and the new situation has to be accommodated, add a com.sun.star.lang.XEventListener at the com.sun.star.lang.XComponent interface. In this case, release the reference on a  notification.

Sometimes it is necessary to exercise more control over the closing process. For this an optional interface com.sun.star.util.XCloseable has been introduced. If the object you are referencing is a com.sun.star.util.XCloseable, register it as a com.sun.star.util.XCloseListener and throw a com.sun.star.util.CloseVetoException when prompted to close. Since  is specified as an optional interface for frames and models, do not assume that this interface is supported. It is possible that the code runs with a LibreOffice version where frames and models do not implement. Therefore, be prepared for the case when you receive null when you try to query. The  interface is described in more detail below.

How to Trigger Closing
The second aspect - to close a view of a component or the entire viewable component yourself - is more complex. The necessary steps depend on how you want to treat modified documents.

The following three diagrams show the decisions to be made when closing a frame or a document model. The important points are: if you expect modifications, you must either handle them using com.sun.star.util.XModifiable and com.sun.star.frame.XStorable, or let the user do the necessary interaction by calling  on the controller. In any case, check if the frame or model is an  and prefer com.sun.star.util.XCloseable:close  over a call to. The first two diagrams illustrate the separate closing process for frames and models, the third diagram covers the actual termination of frames and models.







XCloseable
The dispose mechanism has shortcomings in complex situations, such as the frame-controller-model interaction. The dispose call cannot be rejected, but as shown above, sometimes it is necessary to prevent destruction of objects due to shared ownership or a state of the documents that forbids destruction.

A closing mechanism is required that enables all involved objects to negotiate if deletion is possible and to veto, if necessary. By offering the interface com.sun.star.util.XCloseable, a component tells it must be destroyed by calling. Calling  on an   might lead to deadlocks or crash the entire application.

In LibreOffice, model or frame objects are possible candidates for implementing the interface, therefore query for that interface before destroying the object. Call  directly if the model or frame does not support the interface, thus declaring that it handles all the problems.

An object implementing  registers close listeners. When a close request is received, all listeners are asked for permission. If a listener wants to deprecate, it throws an exception derived from com.sun.star.util.CloseVetoException containing the reason why the component can not be closed. This exception is passed to the close requester. The  itself can veto the destruction by throwing an exception. If there is no veto, the  calls   on itself and returns.

The  handles problems that occur if a component rejects destruction. A script programmer usually can not cope with a component not used anymore that refuses to be destroyed. Ensure that the component is destroyed to avoid a memory leak. The  method offers a method to pass the responsibility to close the object to any possible close listener that vetoes closing or to the   if the initial caller is not able to stay in memory to try again later. This responsibility is referred to as delivered ownership. The mechanism sets some constraints on the possible reasons for an objection against a close request.

A close listener that is asked for permission can object for any reason if the close call does not force it to assume ownership of the closeable object.The close requester is aware of a possible failure. If the close call forces the ownership, the close listener must be careful. An objection is only allowed if the reason is temporary. As soon as the reason no longer exists, the owner automatically calls close on the object that should be closed, now being in the same situation as the initial close requester.

A permanent reason for objection is not allowed. For example, the document being modified is not a valid reason to object, because it is unlikely that the document becomes unmodified by itself. Consequently, it could never be closed. Therefore, if an API programmer wants to avoid data loss, he must use the com.sun.star.util.XModifiable and com.sun.star.frame.XStorable interfaces of the document. The fact that a model refuses to be closed if it is modified is not dependable.

The interface com.sun.star.util.XCloseable inherits from com.sun.star.util.XCloseBroadcaster and has the following methods:

The com.sun.star.util.XCloseListener is notified twice when  is called on an   :

com.sun.star.util.XCloseable:close and com.sun.star.util.XCloseListener:queryClosing  throw a com.sun.star.util.CloseVetoException.

In the closing negotiations, an  is asked to close itself. In the call to close, the caller passes a boolean parameter  to tell the   that it will give up ownership in favor of an , or the   that might have to finish a job first, but will close the   immediately when the job is completed.

After a call to, the   notifies its listeners twice. First, it checks if it can be closed. If not, it throws a, otherwise it uses   to see if a listener has any objections against closing. The value of  is conveyed in the   parameter of. If no listener disapproves of closing, the  exercises   on the listeners and disposes itself. The result of a call to  on a model is that all frames, controllers and the model itself are destroyed. The result of a call to  on a frame is that this frame is closed, but the model stays alive if there are other controllers.

If an  does not agree on closing, it throws a , and the   lets the exception pass in  , so that the caller receives the exception. The  tells the caller that closing failed. If the caller delegated its ownership in the call to close by setting the  parameter to true, an   knows that it automatically assumes ownership by throwing a. The caller knows that someone else is now the owner if it receives a. The new owner is compelled to close the  as soon as possible. If the  was the object that threw an exception, it is compelled also to close itself as soon as possible.

If a model object supports, calling   on it is forbidden, try to   the   and catch a possible. Components that cannot cope with a destroyed model add a close listener at the model. This enables them to object when the model receives a  request. They also add as a close listener if they are not already added as an (dispose) event listener. This can be done by every controller object that uses that model. It is also possible to let the model iterate through its controllers and call their  methods explicitly as a part of its implementation of the close method. It is only necessary to know that a method  must be called to close the model with its controllers. The method the model chooses is an implementation detail.

The example below closes a loaded document component. It does not save modified documents or prompts the user to save.

Storing Documents
After loading an office component successfully, the returned interface is used to manipulate the component. Document specific interfaces, such as the interfaces com.sun.star.text.XTextDocument, com.sun.star.sheet.XSpreadsheetDocument or com.sun.star.drawing.XDrawPagesSupplier are retrieved using.

If the office component supports the com.sun.star.frame.XStorable interface applying to every component implementing the service com.sun.star.document.OfficeDocument, it can be stored:

The  offers the methods ,   and   for storing. The latter two methods are called with a media descriptor.

The method  overwrites an existing file. Calling this method on a document that was created from scratch using a private:factory/... URL leads to an exception.

The other two methods  and   leave the original file untouched and differ after the storing procedure. The  method saves the current document to the desired location without touching the internal state of the document. The method  sets the   attribute of the document, accessible through its com.sun.star.util.XModifiable interface, to   and updates the internal media descriptor of the document with the parameters passed in the call. This changes the document URL.

The following example exports a Writer document, Writer/Web document or Calc sheet to HTML.

If a model is loaded or stored successfully, all parts of the media descriptor not explicitly excluded according to the media descriptor table in section MediaDescriptor must be provided by the methods  and   in the com.sun.star.frame.XModel interface. The separation of the URL and the other arguments is used, because the URL is often the most wanted part for its performance optimized access.

Printing Documents
Printing revolves around the interface com.sun.star.view.XPrintable. Its methods and special printing features for the various document types are described in the document chapters Printing Text Documents, Printing Spreadsheet Documents, Printing Drawing Documents and Printing Presentation Documents.

Using the Dispatch Framework
The component framework with the Frame-Controller-Model paradigm builds the skeleton of the global object structure. Other frameworks are defined that enrich the communication between an office component and the desktop environment. Usually they start at a frame object for the frame anchors an office component in the desktop environment.

One framework is the dispatch framework. Its main purpose is to define interfaces for a generic communication between an office component and a user interface. This communication process handles requests for command executions and gives information about the various attributes of an office component. Generic means that the user interface does not have to know all the interfaces supported by the office component. The user interface sends messages to the office component and receives notifications.The messages use a simple format. The entire negotiation about supported commands and parameters can happen at runtime, while an application using the specialized interfaces of the component is bound to these interfaces at compile time. This generic approach is achieved by looking at an office component differently, not as objects with method-based interfaces, but as slot machines that take standardized command tokens.

We have discussed the differences between the different document types. The common functionality covers the generic features, that is, an office component is considered to be the entirety of its controller, its model and many document-specific interfaces. To implement a user interface for a component, it would be closely bound to the component and its specialized interfaces. If different components use different interfaces and methods for their implementations, similar functions cannot be visualized by the same user interface implementation. For instance, an action like leads to different interface calls depending on the document type it is sent to. From a user interface perspective, it would be better to define abstract descriptions of the actions to be performed and let the components decide how to handle these actions, or not to handle. These abstract descriptions and how to handle them is specified in the dispatch framework.

Command URL
In the dispatch framework, every possible user action is defined as an executable command, and every possible visualization as a reflection of something that is exposed by the component is defined as an attribute. Every executable command and every attribute is a feature of the office component, and the dispatch framework gives every feature a name called command URL. It is represented by a com.sun.star.util.URL struct.

Command URLs are strings that follow the protocol_scheme:protocol_specific_part pattern. Public URL schemes, such as file: or http can be used here. Executing a request with a URL that points to a location of a document means that this document is loaded. In general, both parts of the command URL can be arbitrary strings, but a request cannot be executed if there is an object that does not know how to handle its command URL.

Processing Chain
A request is created by any object.User interface objects can create requests. Consider a toolbox where different functions acting on the office component are presented as buttons. When a button is clicked, the desired functionality is executed. If the code assigned to the button is provided with a suitable command URL, it handles the user action by creating the request and finding a component that can handle it. The button handler does not require any prior knowledge of the component and how it would go about its task.

This situation is handled by the design pattern chain of responsibility. Everything a component needs to know to execute a request is the last link of a chain of objects capable of executing requests. If this object gets the request, it checks if it can handle it or passes it to the next chain member until the request is executed, or the end of the chain is reached.

The chain members in the dispatch framework are objects implementing the interface com.sun.star.frame.XDispatchProvider. Every frame and controller supports it.In the simplest case, the chain consists of two members, a frame and its controller, but concatenating several chain parts on demand of a frame or a controller is possible. Once called, a controller passes on the call, that is, it can use internal frames created by its implementation. A frame also passes the call to other objects, for example, its parent frame.

The current implementation of the chain is different from a simple chain. A frame is always the leading chain member and must be called initially, but in the default implementation used in LibreOffice, the frame first asks its controller before it goes on with the request. Other frame implementations handle this in a different way. Other chain members are inserted into the call sequence before the controller uses the dispatch interception capability of a frame. The developers should not rely on any particular order inside the chain.

The dispatch framework uses a generic approach to describe and handle requests with a lose coupling between the participating objects. To work correctly, it is necessary to follow certain rules:


 * 1) Every chain starts at a frame, and this object decides if it passes on the call to its controller. The controller is not called directly from the outside. This is not compulsory for internal usage of the dispatch API inside an office component implementation. The two reasons for this rule are:
 * A frame provides a com.sun.star.frame.XDispatchProviderInterception interface, where other dispatch providers dock. The frame implementation guarantees that these interceptors are called before the frame handles the request or passes it to the controller. This allows a sophisticated customization of the dispatch handling.
 * If a component is placed into a context where parts of its functionality are not to be exposed to the outside, a special frame implementation is used to suppress or handle requests before they are passed to the controller. This frame can add or remove arguments to requests and exchange them.

A command URL is parsed into a com.sun.star.util.URL struct before passing it to a dispatch provider, because it is assumed that the call is passed on to several objects. Having a pre-parsed URL saves parsing the command string repeatedly. Parsing means that the members,  ,   and at least one more member of the com.sun.star.util.URL struct, depending on the given protocol scheme have to be set. Additional members are set if the concrete URL protocol supports them. For well known protocol schemes and protocol schemes specific to LibreOffice, the service com.sun.star.util.URLTransformer is used to fill the struct from a command URL string. For other protocols, the members are set explicitly, but it is also possible to write an extended version of the URLTransformer service to carry out URL parsing. An extended  must support all protocols supported by the default   implementation, for example, by instantiating the old implementation by its implementation name and forwarding all known URLs to it, except URLs with new protocols.

The dispatch framework connects an object that creates a request with another object that reacts on the request. In addition, it provides feedback to the requester. It can tell if the request is currently allowed or not. If the request acts on a specific attribute of an object, it provides the current status of this attribute. Altogether, this is called status information, represented by a com.sun.star.frame.FeatureStateEvent struct. This information is reflected in a user interface by enabling or disabling controls to show their availability, or by displaying the status of objects. For example, a pressed button for the bold attribute of text, or a numeric value for the text height in a combo box.

The com.sun.star.frame.XDispatchProvider interface does not handle requests, but delegates every request to an individual dispatch object implementing com.sun.star.frame.XDispatch.

Dispatch Process
This section describes the necessary steps to handle dispatch providers and dispatch objects. The illustration below shows the services and interfaces of the the Dispatch framework.



Getting a Dispatch Object
First, create a command URL that represents the desired functionality ensuring that it is parsed as described above. Tables with possible command URLs for the default office components of LibreOffice are located in the appendix.

Request the com.sun.star.frame.XDispatchProvider interface of the frame that contains the office component for a dispatch object for the command URL by calling its  method.

The additional parameters of this call are only used for dispatching public URL schemes, because they specify a target frame and frame search mode to the loading process. Valid target names and search flags are described in the section Target Frame. The targets " ", " " and " " are well-defined, so that they can be used, because a  call starts at a frame object. Using frame names or search flags with command URLs does not have any meaning in the office components in LibreOffice.

You receive a dispatch object that supports at least com.sun.star.frame.XDispatch :

Listening for Status Information
If a dispatch object is received, add a listener for status events by calling its  method. A com.sun.star.frame.XStatusListener implements:

Keep a reference to the dispatch object until you call the  method, because it is not sure that any other object will keep it alive. If a status listener is not registered, because you want to dispatch a command, and are not interested in status events, release all references to the dispatch object immediately after usage. If a dispatch object is not received, the desired functionality is not available. If you have a visual user interface element that represents that functionality, disable it.

If a status listener is registered and there is status information, a com.sun.star.frame.FeatureStateEvent is received immediately after registering the listener. Status information is still received later if the status changes and you are still listening. The  member of the com.sun.star.frame.FeatureStateEvent tells you if the functionality is currently available, and the   member holds information about a status that could be represented by UI elements. Its type depends on the command URL. A boolean status information is visualized in a pressed or not pressed look of a toolbox button. Other types need complex elements, such as combo boxes or spinfields embedded in a toolbox that show the current font and font size. If the  member is empty, the action does not have an explicit status, such as the menu item. The current status can be ambiguous, because more than one object is selected, and the objects are in a different status, for example. selected text that is partly formatted bold and partly regular.

A special event is a status event where the  flag is set. This is a request to release all references to the dispatch object and to ask the dispatch provider for a new object, because the old one has become invalid. This allows the office components to accommodate internal context changes. It is possible that a dispatch object is not received, because the desired functionality has become unavailable.

If you do not get any status information in your  implementation, assume that the functionality is always available, but has no explicit status.

If you are no longer interested in status events, use the  method and release all references to the dispatch object. You may get a  callback from the dispatch object when it is going to be destroyed. It is not necessary to call. Ensure that you do not hold any references to the dispatch object anymore.

Listening for Context Changes
Sometimes internal changes, for example, traveling from a text paragraph to a text table, or selecting a different type of object, force an office component to invalidate all referenced dispatch objects and provides other dispatch objects, including dispatches for command URLs it could not handle before. The component then calls the  method of its frame, and the frame broadcasts the corresponding com.sun.star.frame.FrameActionEvent. For this reason, register a frame action listener using addFrameActionListener at frames you want dispatch objects. Refer to section Frame Actions for additional information. If the listener is called back with a CONTEXT_CHANGED event, release all dispatch objects and query new dispatch objects for every command URL you require. You can also try command URLs that did not get a dispatch object before.

If you are no longer interested in context changes of a frame, use the  method of the frame to deregister and release all references to the frame. If you get a  request from the frame in between, it is not necessary to call , but you must release all frame references you are currently holding.

Dispatching a Command
If the desired functionality is available, execute it by calling the  method of the dispatch object. This method is called with the same command URL you used to get it, and optionally with a sequence of arguments of type com.sun.star.beans.PropertyValue that depend on the command. It is not redundant that supplied the URL again, because it is allowed to use one dispatch object for many command URLs. The appendix shows the names and types for the parameters. However, the command URLs for simple user interface elements, such as menu entries or toolbox buttons send no parameters. Complex user interface elements use parameters, for example, a combo box in a toolbar that changes the font height.

Dispatch Results
Every dispatch object implements optional interfaces. An important extension is the com.sun.star.frame.XNotifyingDispatch interface for dispatch results. The  call is a   method and should be treated as an asynchronous or oneway call. Therefore a dispatch result can not be passed as a return value; rather, a callback interface is necessary. The interface that provides dispatch results by a callback is the com.sun.star.frame.XNotifyingDispatch interface:

Its method  takes a com.sun.star.frame.XDispatchResultListener interface that is called after a dispatched URL has been executed.

The dispatch result is transferred as a com.sun.star.frame.DispatchResultEvent struct in the callback method. The State member of this struct tells if the dispatch was successful or not, while the Result member contains the value that would be returned if the call had been executed as a synchronous function call. The appendix shows the types of return values. If a public URL is dispatched, the dispatch result is a reference to the frame the component was loaded into.

Dispatch Interception
The dispatch framework described in the last chapter establishes a communication between a user interface and an office component. Both can be LibreOffice default components or custom components. Sometimes it is not necessary to replace a UI element by a new implementation. It can be sufficient to influence its visualized state or to redirect user interactions to external code. This is the typical use for dispatch interception.

The dispatch communication works in two directions: status information is transferred from the office component to the UI elements and user requests travel from the UI element to the office component. Both go through the same switching center, that is, an object implementing com.sun.star.frame.XDispatch. The UI element gets this object by calling  at the frame containing the office component, and usually receives an object that connects to code inside the frame, the office component or global services in LibreOffice. The frame offers an interface that is used to return third-party dispatch objects that provide the UI element with status updates. For example, it is possible to disable a UI element that would not be disabled otherwise. Another possibility is to write replacement code that is called by the UI element if the user performs a suitable action.

Dispatch objects are provided by objects implementing the com.sun.star.frame.XDispatchProvider interface, and that is the interface you are required to implement. There is an extra step where the dispatch provider must be attached to the frame to intercept the dispatching communication, therefore the dispatch provider becomes a part of the chain of responsibility described in the previous section. This is accomplished by implementing com.sun.star.frame.XDispatchProviderInterceptor.

This chain usually only consists of the frame and the controller of the office component it contains, but the frame offers the com.sun.star.frame.XDispatchProviderInterception interface where other providers are inserted. They are called before the frame tries to find a dispatch object for a command URL, so that it is possible to put the complete dispatch communication in a frame under external control. More than one interceptor can be registered, thus building a bigger chain.

Routing every dispatch through the whole chain becomes a performance problem, because there could be scores of possible clients asking for a dispatch object. For this reason, there is also an API that limits the routing procedure to particular commands or command groups. This is described below.

Once the connection is established, the dispatch interceptor decides how requests for a dispatch object are dealt with. When asked for a dispatch object for a Command URL, it can:


 * Return an empty interface that disables the corresponding functionality.
 * Pass the request to the next chain member, called slave dispatch provider described below if it is not interested in that functionality.
 * Handle the request and return an object implementing com.sun.star.frame.XDispatch . As described in the previous chapter, client objects may register at this object as status event listeners. The dispatch object returns any possible status information as long as the type of the "State" member in the com.sun.star.frame.FeatureStateEvent struct has one of the expected types, otherwise the client requesting the status information can not handle it properly. The expected types must be documented together with the existing commands.For example, if a menu entry wants status information, it handles a, meaning nothing special should be done, or a   state by displaying a check mark, but nothing else. The status information could contain a   directive. Note that a dispatch object returns status information immediately when a listener registers. Any change events can be broadcast at arbitrary points in time.
 * The returned dispatch object is also used by client objects to dispatch the command that matches the command URL. The dispatch object receiving this request checks if the code it wants to execute is valid under the current conditions. It is not sufficient to rely on disable requests, because a client is not forced to register as a status listener if it wants to dispatch a request.

The slave dispatch provider and master dispatch provider in the com.sun.star.frame.XDispatchProviderInterceptor interface are a bit obscure at first. They are two pointers to chain members in both directions, next and previous, where the first and last member in the chain have special meanings and responsibilities.

The command dispatching passes through a chain of dispatch providers, starting at the frame. If the frame is answered to include an interceptor in this chain, the frame inserts the interceptor in the chain and passes the following chain member to the new chain member, so that calls are passed along the chain if it does not want to handle them.

If any interceptor is deregistered, the frame puts the loose ends together by adjusting the master and slave pointer of the chain successor and predecessor of the element that is going to be removed from the chain. All of them are interceptors, so only the last slave is a dispatch provider.

The frame takes care of the whole chain in the register or deregister of calls in the dispatch provider interceptor, so that the implementer of an interceptor does not have to be concerned with the chain construction.

Java Window Integration
This section discusses experiences obtained during the development of Java-LibreOffice integration. Usually, developers use the OfficeBean for this purpose. The following provides background information about possible strategies to reach this goal.

There are multiple possibilities to integrate local windows with LibreOffice windows. This chapter shows the integration of LibreOffice windows into a Java bean environment. Some of this information may be helpful with other local window integrations.

The Window Handle
An important precondition is the existence of a system window handle of the own Java window. For this, use a  and the following JNI methods:


 * a method to query the window handle (HWND on Windows, X11 ID on UNIX)
 * a method to identify the operating system, for example, UNIX, Windows, or Macintosh

For an example, see bean/com/sun/star/beans/LocalOfficeWindow.java

The two methods  and   are declared and exported, but implemented for windows in bean/native/win32/com_sun_star_beans_LocalOfficeWindow.c through JNI

Using the Window Handle
The window handle create the LibreOffice window. There are two ways to accomplish this:

A Hack
This option is mentioned because there are situations where this is the only feasible method. The knowledge of this option can help in other situations.

Add the UNO interface com.sun.star.awt.XWindowPeer so that it is usable for the LibreOffice window toolkit. This interface can have an empty implementation. In com.sun.star.awt.XToolkit:createWindow, another interface com.sun.star.awt.XSystemDependentWindowPeer is expected that queries the HWND. Thus,  is for transporting and com.sun.star.awt.XSystemDependentWindowPeer queries the HWND.

This method gets a com.sun.star.awt.XWindow as a child of your own Java window, that is used to initialize a com.sun.star.frame.XFrame.

Legal Solution
The com.sun.star.awt.Toolkit service implements the interface com.sun.star.awt.XSystemChildFactory with a method. This accepts an any with a wrapped HWND or X Window ID, as long and the system type, such as Windows, Java, and UNIX directly. Here you create an com.sun.star.awt.XWindow. This method cannot be used in LibreOffice build versions before src642, because the process ID parameter is unknown to the Java environment. Newer versions do not check this parameter, thus this new, method works.

Resizing
Another difficulty is resizing the window. Normally, the child window expects resize events of the parent. The child does not resize it window, because it must know the layout of the parent window. The VCL, LibreOffice's windowing engine creates a special system child window, thus we can resize windows.

The parent window can be filled "full size" with the child window, but only for UNIX and not for Windows. The VCL's implementation is system dependent.

The bean deals with this issue by adding another function to the local library. Windows adds arbitrary properties to an HWND. You can also subclass the window, that is, each Windows window has a function pointer or callback to the function that performs the event handling (WindowProcedure). Using this, it is possible to treat events by calling your own methods. This is useful whenever the window is not created by you and you need to influence the behavior of the window.

In this case, the Java window has not been created by us, but we need to learn about resize events to forward these to the LibreOffice window. Look at the file bean/native/win32/com_sun_star_beans_LocalOfficeWindow.c, and find the method. In the first call of the JNI function  of this file, the own handler is applied to the foreign window.

In the future, VCL will do this sub-classing by itself, even on Windows. This will lead to equal behavior between Windows and UNIX.

The initial size of the window is a related problem. If a canvas is connected with a LibreOffice window, set both sizes to a valid, positive value, otherwise the LibreOffice window will not be visible. If you are using a non-product build of OpenOffice.org, you see an assertion failed "small world isn't it". This might change when the sub-classing is done by VCL in the future.

There is still one unresolved problem. The code mentioned above works with Java 1.3, but not for Java 1.4. There, the behavior of windows is changed. Where Java 1.3 sends real resize events from the own, Java 1.4 does a re-parenting. The canvas window is destroyed and created again. This leads to an empty window with no LibreOffice window. This problem is under investigation.

More Remote Problems
There are additional difficulties to window handles and local window handles. Some personal experiences of one of the LibreOffice authors are provided:


 * Listeners in Java should be implemented in a thread. The problem is that SolarMutex, a mutex semaphore of LibreOffice, one-way UNO methods and the global Java GUI thread do not work together.
 * The Java applet should release its listeners. If they stay in the containers of LibreOffice after the Java process ends, UNO throws a com.sun.star.lang.DisposedException, which are not caught correctly. Java does not know destructors, therefore it is a difficult to follow this advice. One possibility is to register a Thread object at  as a  . This is called even when CTRL-C is pressed on the command line where you can deregister the listeners. Because listeners are threads, there is some effort.

Clipboard
This chapter introduces the usage of the clipboard service com.sun.star.datatransfer.clipboard.SystemClipboard. The clipboard serves as a data exchange mechanism between LibreOffice custom components, or between custom components and external applications. It is usually used for copy and paste operations.

Different platforms use different methods for describing data formats available on the clipboard. Under Windows, clipboard formats are identified by unique numbers, for example, under X11, a clipboard format is identified by an ATOM. To have a platform independent mechanism, the LibreOffice clipboard supports the concept of DataFlavors. Each instance of a DataFlavor represents the opaque concept of a data format as it would appear on a clipboard. A DataFlavor defined in com.sun.star.datatransfer.DataFlavor has three members:

The carrier of the clipboard data is a transferable object that implements the interface com.sun.star.datatransfer.XTransferable. A transferable object offers one or many different DataFlavors.

Pasting Data
The following Java example demonstrates the use of the clipboard service to paste from the clipboard.

Copying Data
To copy to the clipboard, implement a transferable object that supports the interface com.sun.star.datatransfer.XTransferable. The transferable object offers arbitrary formats described by DataFlavors.

The following Java example demonstrates the implementation of a transferable object. This transferable object contains only one format, unicode text.

Everyone providing data to the clipboard becomes a clipboard owner. A clipboard owner is an object that implements the interface com.sun.star.datatransfer.clipboard.XClipboardOwner. If the current clipboard owner loses ownership of the clipboard, it receives a notification from the clipboard service. The clipboard owner can use this notification to destroy the transferable object that was formerly on the clipboard. If the transferable object is a self-destroying object, destroying clears all references to the object. If the clipboard service is the last client, clearing the reference to the transferable object leads to destruction.

All data types except for text have to be transferred as byte array. The next example shows this for a bitmap.

The following Java example shows an implementation of the interface com.sun.star.datatransfer.clipboard.XClipboardOwner.

The last two samples combined show how it is possible to copy data to the clipboard as demonstrated in the following Java example.

Becoming a Clipboard Viewer
It is useful to listen to clipboard changes. User interface controls may change their visible appearance depending on the current clipboard content. To avoid polling on the clipboard, the clipboard service supports an asynchronous notification mechanism. Every client that needs notification about clipboard changes implements the interface com.sun.star.datatransfer.clipboard.XClipboardListener and registers as a clipboard listener. Implementing the interface com.sun.star.datatransfer.clipboard.XClipboardListener is simple as the next Java example demonstrates.

If the interface was implemented by the object, it registers as a clipboard listener. A clipboard listener deregisters if clipboard notifications are no longer necessary. Both aspects are demonstrated in the next example.

LibreOffice Clipboard Data Formats
This section describes common clipboard data formats that LibreOffice supports and their corresponding DataType.

As previously mentioned, data formats are described by DataFlavors. The important characteristics of a DataFlavor are the MimeType and DataType. The LibreOffice clipboard service uses a standard MimeType for different data formats if there is one registered at Iana. For example, for HTML text, the MimeType " " is used, Rich Text uses the MimeType " ", and text uses " ". If there is no corresponding MimeType registered at Iana, LibreOffice defines a private MimeType. Private LibreOffice MimeType always has the MimeType " ". Each private LibreOffice MimeType has a parameter "windows_formatname" identifying the clipboard format name used under Windows. The used Windows format names are the format names used with older LibreOffice versions. Common Windows format names are " ", " ", " ", " ", and " ". The DataType of a DataFlavor identifies how the data are exchanged. There are only two DataTypes that can be used. The DataType for Unicode text is a string, and in Java,, For all other data formats, the DataType is a sequence of bytes in Java.

The following table lists common data formats, and their corresponding MimeType and DataTypes:

Internationalization
The I18N framework provides interfaces to access locale-dependent data (e.g. calendar data, currency) and methods (e.g. collation and transliteration). The I18N framework offers full-featured internationalization functionality that covers a range of geographic locations that include East Asia (China, Japan, and Korea, or CJK), Europe, Middle East (Hebrew, Arabic) and South-East Asia (Thai, Indian). Also, the I18N framework builds on the component model UNO, thus making the addition of new internationalization components easy.

Introduction
The I18N framework contains a lot of data and many interfaces and methods not important to developers of external code using the LibreOffice API, but only for developers of the LibreOffice application itself. This chapter is split into two parts, one that gives a short overview on using the API and is restricted to what is useful to external developers, and a second part that focuses on how to implement a new locale supporting the API (Note that this section does not cover how to translate and localize the LibreOffice resources).

XLocaleData
The com.sun.star.i18n.XLocaleData interface provides access to locale-specific information, such as decimal separators, group (thousands) separators, currency information, calendar data, and number format codes. No further functionality is discussed.

XCharacterClassification
The com.sun.star.i18n.XCharacterClassification interface is used to determine the Unicode type of a character (such as uppercase, lowercase, letter, digit, punctuation) or the script type. It also provides methods to perform simple uppercase to lowercase and lowercase to upper case conversions that are locale-dependent but do not need real transliteration. An example of locale-dependent case conversion is the Turkish lowercase i to uppercase I-dot and lowercase i-dotless to uppercase I conversion, as opposed to the western lowercase i to uppercase I conversion.

Another provided functionality is parsing methods to isolate and determine identifiers, numbers, and quoted strings in a given string. See the description of com.sun.star.i18n.XCharacterClassification methods  and. The parser uses com.sun.star.i18n.XLocaleData to obtain the locale-dependent decimal and group separators.

XCalendar
The com.sun.star.i18n.XCalendar interface enables the application to use any calendar available for a given locale, not being restricted to the Gregorian calendar. You may query the interface for the available calendars for a given locale with method  and load one of the available calendars using method , or you may use the default calendar loaded with method. Normally, a Gregorian calendar is available with the name " " in the Name field of com.sun.star.i18n.Calendar even if the default calendar is not a Gregorian calendar, but this is not mandatory. Available calendars are obtained through the com.sun.star.i18n.XLocaleData interface.

XExtendedCalendar
The com.sun.star.i18n.XExtendedCalendar interface was introduced with OpenOffice.org 1.1.0 and provides additional functionality to display locale and calendar dependent calendar values. This interface is derived from com.sun.star.i18n.XCalendar. The interface provides a method to obtain display strings of date parts for specific calendars of a specific locale.

XNumberFormatCode
The com.sun.star.i18n.XNumberFormatCode interface provides access to predefined number format codes for a given locale, which in turn are obtained through the com.sun.star.i18n.XLocaleData interface. Normally you do not need to bother with it because the application's number formatter Number Formats manages the codes. It just might serve to get the available codes and determine default format codes of a specific category.

XNativeNumberSupplier
The com.sun.star.i18n.XNativeNumberSupplier interface was introduced with OpenOffice.org 1.1.0 and provides functionality to convert between ASCII Arabic digits/numeric strings and native numeral strings, such as Korean number symbols.

XCollator
The com.sun.star.i18n.XCollator interface provides locale-dependent collation algorithms for sorting purposes. There is at least one collator algorithm available per locale, though there may be more than one, for example  and   algorithms, or ,  ,   in Chinese locales. There is always one default algorithm for each locale that may be loaded using method, and all available algorithms may be queried with method   of those a selected algorithm may be loaded using. The available collator implementations and options are obtained through the com.sun.star.i18n.XLocaleData interface.

XTransliteration
The com.sun.star.i18n.XTransliteration interface provides methods to perform locale-dependent character conversions, such as case conversions, conversions between Hiragana and Katakana, and Half-width and Full-width. Transliteration is also used by the collators if, for example, a case insensitive sort is to be performed. The available transliteration implementations are obtained through the com.sun.star.i18n.XLocaleData interface.

XTextConversion
The com.sun.star.i18n.XTextConversion interface provides methods to perform locale-dependent text conversions, such as Hangul/Hanja conversion for Korean, or translation between Chinese simplified and Chinese traditional.

XBreakIterator
The com.sun.star.i18n.XBreakIterator interface may be used to traverse the text in character mode or word mode, to jump to the beginning or to the end of a sentence, to find the beginning or the end of a given script type, and, as the name suggests, to determine a line break position, optionally using a com.sun.star.linguistic2.XHyphenator. The service implementation obtains lists of forbidden characters (characters that are not allowed at the beginning or the end of a line in certain locales) through the com.sun.star.i18n.XLocaleData interface. The  interface also offers methods to determine the script type of a character or to find the beginning or end of a script type along a sequence of characters.

XIndexEntrySupplier
The com.sun.star.i18n.XIndexEntrySupplier interface may be used to obtain information on index entries to generate a "table of alphabetical index" for a given locale. Since not all languages are alphabetical in the western sense (for example, CJK languages), different methods are needed.

XExtendedIndexEntrySupplier
The com.sun.star.i18n.XExtendedIndexEntrySupplier interface was introduced with OpenOffice.org 1.1.0 and provides additional functionality to generate index entries for languages that need phonetically sorted indexes, such as Japanese. The interface is derived from com.sun.star.i18n.XIndexEntrySupplier.

The com.sun.star.i18n.XInputSequenceChecker interface was introduced with OpenOffice.org 1.1.0 and provides input sequence checking for Thai and Hindi.

XLocaleData
One of the most important tasks in implementing a new locale is to define all the locale data to be used, listed in the following table as types returned by the com.sun.star.i18n.XLocaleData interface methods:

Locale data is defined in an XML file. It is translated into a C++ source file during the build process, which is compiled and linked together with other compiled locale data files into shared libraries. The contents of the XML file, their elements, and how they are to be defined are described in i18npool/source/localedata/data/locale.dtd. The latest revision available for a specific CVS branch of that file provides up-to-date information about the definitions, as well as additional information.

If the language-country combination is not already listed in tools/inc/lang.hxx and tools/source/intntl/isolang.cxx and svx/source/dialog/langtab.src, LibreOffice is probably not prepared to deal with your specific locale. For assistance, you can consult https://openoffice.apache.org/translate.html and join the dev@openoffice.apache.org mailing list (see also https://openoffice.apache.org/mailing-lists.html#localization-mailing-list-public).

In order to conform with the available build infrastructure, the name of your locale data file should follow the conventions used in the i18npool/source/localedata/data directory:  _ .xml, where language is a lowercase, two letter ISO-639 code, and country is an uppercase two letter ISO-3166 code. Start by copying the en_US.xml file to your  _ .xml file and adapt the entries to suit your needs. Add the corresponding *.cxx and *.obj target file name to the i18npool/source/localedata/data/makefile.mk. Note that there is an explicit rule defined, so that you do not need to add the *.xml file name anywhere. You must also add the locale to the  structure located in i18npool/source/localedata/data/localedata.cxx. Make sure to specify the correct library name, since it must correspond to the library name used in the makefile. Finally, the public symbols to be exported must be added to the linker map file corresponding to the library. You can use the i18npool/source/localedata/data/linkermapfile-check.awk script to assist you. Instructions for how to use the script are located the header comments of the file.


 * To be able to load documents of versions up to and including StarOffice 5.2 (old binary file format), each locale must define all number formats mentioned in com.sun.star.i18n.NumberFormatIndex and assign the proper  attribute.
 * Failing to do so may result in data not properly displayed or not displayed at all if a built-in "System" or "Default" format code was used (as generally done by the average user) and the document is loaded under a locale not having those formats defined. Since old versions did merge some format information of the [Windows] Regional Settings, it might be necessary to define some duplicated codes to fill all positions. To verify that all necessary elements are defined, use a non-product build of OpenOffice.org and open a number formatting dialog, and select your locale from the Language list box. An assertion message box appears if there are any missing elements. The errors are only shown the very first time the locale is selected in a given document.


 * In general, definition of number format codes follows the user visible rules, apart from that any non-ASCII character must be entered using UTF-8 encoding. For a detailed description of codes and a list of possible keywords please consult the LibreOffice English online help on section "number format codes".
 * Be sure to use the separators you declared in the  section in the number format codes, for example ,  , otherwise the number formatter generates incorrect formats.
 * Verify the defined codes again by using the number formatter dialog of a non-product OpenOffice build. If anything is incorrect, an assertion message box appears containing information about the error. The format indices 1..49 are reserved and, for backward compatibility, must be used as stated in offapi/com/sun/star/i18n/NumberFormatIndex.idl. Note that 48 and 49 are used internally and must not be used in locale data XML files. All other formats must be present.

 and 
 * Characters of date and time keywords, such as YYYY for year, had previously been localized for a few locales (for example, JJJJ in German). The new I18N framework no longer follows that approach, because it may lead to ambiguous and case insensitive character combinations that cannot be resolved at runtime. Localized keyword support is only given for some old locales, other locales must define their codes using English notation.
 * The table below shows the localized keyword codes:

 and 
 * The  com.sun.star.i18n.NumberFormatIndex   format code is used to edit date formatted data. It represents a date using the most detailed information available, for example, a 4-digit year and instead of a 2-digit year. The YMD default order (how a date is assembled) is determined from the order encountered in this format.
 * Similarly, the  com.sun.star.i18n.NumberFormatIndex   format code is used to edit date-time data. Both format codes must display data in a way that is parable by the application, in order to be able to reassemble edited data. This generally means using only YYYY,MM,DD,HH,MM,SS keywords and   and.


 * The [$xxx-yyy] notation is needed for compatibility reasons. The xxx part denotes the currency symbol, and the yyy part specifies the locale identifier in Microsoft Language ID hexadecimal notation. For example, having "409" as the locale identifier (English-US) and "$" as the currency symbol results in [$$-409]. A list of available Language IDs known to the [AOo] application can be found at project util module tools in file tools/inc/lang.hxx. Format indices 12, 13, 14, 15, 17 with [$xxx-yyy] notation must use the xxx currency symbol that has the attribute usedInCompatibleFormatCodes="true" (see element  in the locale.dtd file).

XCalendar
The interface com.sun.star.i18n.XCalendar provides a general calendar service. All calendar implementations are managed by a class, the front-end, which dynamically calls a language-specific implementation.

is a wrapper to ICU's Calendar class.

If you need to implement a locale-specific calendar, you can choose to either derive your class from  or to write your own class.

There are three steps needed to create a locale-specific calendar:


 * 1) Name your calendar   (for example, 'gengou' for Japanese Calendar) and add it to the locale data XML file with proper day/month/era names.
 * 2) Derive a class either from   or , name it as  , which will be loaded by   when the calendar is specified.
 * 3) Add your new calendar as a service in i18npool/source/registerservices/registerservices.cxx.

If you plan to derive from the Gregorian calendar, you need to know the mapping between your new calendar and the Gregorian calendar. For example, the Japanese Emperor Era calendar has a starting year offset to Gregorian calendar for each era. You will need to override the method  and   to map the Era/Year/Month/Day between the Gregorian calendar and the calendar for your language.

XCharacterClassification
The interface com.sun.star.i18n.XCharacterClassification provides,  ,   and methods to get various character attributes defined by Unicode. These functions are implemented by the  class. If you need language specific requirements for these functions, you can derive a language specific class  from   and overwrite the methods. In most cases, the attributes are well defined by Unicode, so you do not need to create your own class.

The class also provides a generic parser. If a particular language needs special number parsing, detected non-ASCII numbers are fed to the  service to obtain the ASCII representation, which in turn is interpreted and converted to a double precision floating point value.

A manager class  will handle the loading of language specific implementations of   on the fly. If no implementation is provided, the implementation defaults to class.

XBreakIterator
The interface com.sun.star.i18n.XBreakIterator provides support for Character(Cell)/Word/Sentence/Line-break services. For example,  provides the APIs to iterate a string by character, word, line and sentence. The interface is used by the Output layer for the following operations:


 * Cursor positioning and selection: Since a character or cell can take more than one code point, cursor movement cannot be done by simply incrementing or decrementing the index.
 * Complex Text Layout Languages (CTL): In CTL languages (such as Thai, Hebrew, Arabic and Indian), multiple characters can combine to form a display cell. Cursor movement must traverse a display cell instead of a single character.

Line breaking must be highly configurable in desktop publishing applications. The line breaking algorithm should be able to find a line break with or without a hyphenator. Additionally, it should be able to parse special characters that are illegal if they occur at the end or beginning of a line.

Both requirements are locale-sensitive.

The  components are managed by the class , which will load the language-specific component in service name   dynamically.

The base break iterator class  is a wrapper to the ICU   class. While this class meets the requirements for western languages, it does not meet the requirements for other languages, such as those of South Asia (CJK) and South East Asia (Indian, Thai, Arabic), where enhanced functionality is required, as described previously.

Thus the current  base class has two derived classes,   and. provides a dictionary based word break for Chinese and Japanese, and a forbidden rule driven line break for Chinese, Japanese and Korean. provides a more specific definition of character/cell/cluster grouping for languages like Thai and Arabic.

Use the following steps to create a language-specific  service:


 * 1) Derive a class either from   or , name it as.
 * 2) Add new service in

There are three methods for word breaking:,  ,. You can overwrite them with your own language rules.

provides input string caching and dictionary searching for longest matching. You can provide a sorted dictionary (the encoding must be UTF-8) by creating the following file: i18npool/source/breakiterator/data/ .dict.

The utility  will convert the file to C code, which will be compiled into a shared library for dynamic loading.

All dictionary searching and loading is performed in the  class. The only thing you need to do is to derive your class from  and create an instance of the   with the language name and pass it to the parent class.

XCollator
The interface com.sun.star.i18n.XCollator must be used to provide text collation for the new locale. There are two types of collations, single level and multiple level collation.

Most European and English locales need multiple level collation. LibreOffice uses the ICU collator to cover these needs.

Most CJK languages only require single level collation. There is a two step lookup table that performs the collation for these languages. If you have a new language or algorithm in this category, you can derive a new service from Collator_CJK and provide index and weight tables. Here is a sample implementation:

Front end implementation  will load and cache the language-specific service on the name   dynamically.

The steps to add new services:


 * 1) Derive the new service from the above class
 * 2) Provide the index and weight tables
 * 3) Register the new service in registerservices.cxx
 * 4) Add the new service in the collation section in the locale data file.

XTransliteration
The interface com.sun.star.i18n.XTransliteration can be used for string conversion. The front end implementation  will load and cache specific transliteration services by a predefined enum in com.sun.star.i18n.TransliterationModules or com.sun.star.i18n.TransliterationModulesNew, or dynamically by implementation name.

Transliterations have been defined in three categories:,   and. All of them are derived from.

Ignore services are for ignore case, half/full width, and Katakana/Hiragana. You can derive your new service from it, and overwrite folding/transliteration methods.

services are for one to one mapping, such as converting lowercase to uppercase. The class provides two more services, to take a mapping table or mapping function to do folding and transliteration. You can derive a class from it and provide a table or function for the parent class to do the transliteration.

Numeric services are used to convert a number to a number string in specific languages. It can be used to format Date string and other types of strings.

To add a new transliteration


 * 1) Derive a new class from the three classes previously mentioned.
 * 2) Overwrite folding/transliteration methods or provide a table for the parent to perform the transliteration.
 * 3) Register the new service in registerservices.cxx
 * 4) Add the new service in the transliteration section in the locale data file

XTextConversion
The interface com.sun.star.i18n.XTextConversion can be used for string conversion. The service com.sun.star.i18n.TextConversion implementing the interface provides a function to determine if the text conversion should be interactive or not along with functions that can be used for automatic and interactive conversion.

It is possible to create conversion-dictionaries com.sun.star.linguistic2.XConversionDictionary, which are searched for entries to be used by the text conversion service, thus allowing the user to customize the text conversion.

The following is an example:

XNativeNumberSupplier
The interface com.sun.star.i18n.XNativeNumberSupplier provides the functionality to convert between ASCII Arabic digit numbers and locale-dependent numeral representations. It performs the conversion by implementing special transliteration services. The interface also provides a mechanism to generate attributes to be stored in the XML file format (see the XML file format documentation, section "Common Data Style Attributes", "number:transliteration-..."), as well as a conversion of those XML attributes needed to map back to a specific representation style. If you add a number transliteration for a specific locale and reuse one of the com.sun.star.i18n.NativeNumberMode constants, please add the description to com.sun.star.i18n.NativeNumberMode if your changes are to be added back to the OpenOffice.org code repository.

XIndexEntrySupplier
The interface com.sun.star.i18n.XIndexEntrySupplier can be used to provide the functionality to generate index pages. The main method of this interface is. Front end implementation  will dynamically load and cache language specific service based on the name.

Languages to be indexed have been divided into two sets. The first set contains Latin1 languages, which can be covered by 256 Unicode code points. A one step lookup table is used to generate index characters. An alphabetic and numeric table has been generated, which covers most Latin1 languages. But if you need another algorithm or have a conflict with the table, you can create your own table and derive a new class from. Here is a sample implementation:

where  is the table.

For the languages that could not be covered in the first set, such as CJK, a two step lookup table is used. Here is a sample implementation:

where  and   are two step tables and   contains all the index keys that will be returned. If you have a new language or algorithm, you can derive a new service from  and provide tables for the parent class to generate the index.

Note that the index depends on collation, therefore, each index algorithm should have a collation algorithm to support it.

To add new service:


 * 1) Derive the new service from.
 * 2) Provide a table for the lookup
 * 3) Register new service in

A Comment on Search and Replace
Search and replace is also locale-dependent because there may be special search options that are only available for a particular locale. For instance, if the Asian languages support is enabled, you'll see an additional option for "Sounds like (Japanese)" in the dialog box. With this option, you can turn on or off certain options specific to Japanese in the search and replace process.

Search and replace relies on the transliteration modules for various search options. The transliteration modules are loaded, and the search string is converted before the search process.

Linguistics
The Linguistic API provides a set of UNO services used for spell checking, hyphenation or accessing a thesaurus. Through the Linguistic API, developers add new implementations and integrate them into LibreOffice. Users of the Linguistic API call its methods Usually this functionality is used by one or more clients, that is, applications or components, to process documents such as text documents or spreadsheets.

Services Overview
The services provided by the Linguistic API are:


 * com.sun.star.linguistic2.LinguServiceManager
 * com.sun.star.linguistic2.DictionaryList
 * com.sun.star.linguistic2.LinguProperties

Also there is at least one or more implementation for each of the following services:


 * com.sun.star.linguistic2.SpellChecker
 * com.sun.star.linguistic2.Hyphenator
 * com.sun.star.linguistic2.Thesaurus

The service implementations for spell checker, thesaurus and hyphenator supply the respective functionality. Each of the implementations support a different set of languages. Refer to com.sun.star.linguistic2.XSupportedLocales.

For example, there could be two implementations for a spell checker, usually from different supporting parties: the first supporting English, French and German, and the second supporting Russian and English. Similar settings occur for the hyphenator and thesaurus.

It is not convenient for each application or component to know all these implementations and to choose the appropriate implementation for the specific purpose and language, therefore a mediating instance is required.

This instance is the. Spell checking, hyphenation and thesaurus functionality is accessed from a client by using the respective interfaces from the.

The  dispatches the interface calls from the client to a specific service implementation, if any, of the respective type that supports the required language. For example, if the client requires spell checking of a French word, the first spell checker implementations from those mentioned above are called.

If there is more than one spell checker available for one language, as in the above example for the English language, the  starts with the first one that was supplied in the   method of its interface. The thesaurus behaves similarly. For more details, refer to the interface description com.sun.star.linguistic2.XLinguServiceManager.

The  service provides, among others, properties that are required by the spell checker, hyphenator and thesaurus that are modified by the client. Refer to the com.sun.star.linguistic2.LinguProperties.

The  (see com.sun.star.linguistic2.DictionaryList ) provides a set of user defined or predefined dictionaries for languages that are activated and deactivated. If they are active, they are used by the spell checker and hyphenator. These are used by the user to override results from the spell checker and hyphenator implementations, thus allowing the user to customize spell checking and hyphenation.

In the code snippets and examples in the following chapters, we will use the following members and interfaces:

To establish a connection to the office and have our  object initialized with its , the following code is used:

And the  object   is initialized like in the following snippet:

The empty list of temporary property values used for the current function call only and the language used may look like the following:

Using temporary property values:

To change a value for the example  to a different value for one or a limited number of calls without modifying the default values, provide this value as a member of the last function argument used in the examples below before calling the respective functions.

Replace the  argument in the function calls with   to override the value of   from the. Other properties are overridden by adding them to the  object.

Using Spellchecker
The interface used for spell checking is com.sun.star.linguistic2.XSpellChecker. Accessing the spellchecker through the  and initializing the   object is done by:

Relevant properties
The properties of the  service evaluated by the spell checker are:

Changing the values of these properties in the  affect all subsequent calls to the spell checker. Instantiate a com.sun.star.linguistic2.LinguProperties instance and change it by calling com.sun.star.beans.XPropertySet:setPropertyValue. The changes affect the whole office unless another modifies the properties again. This is done implicitly when changing the linguistic settings through.

The following example shows verifying single words:

The following example shows spelling a single word and retrieving possible corrections:

For a description of the return types interface, refer to com.sun.star.linguistic2.XSpellAlternatives.

Using Hyphenator
The interface used for hyphenation is com.sun.star.linguistic2.XHyphenator. Accessing the hyphenator through the  and initializing the   object is done by:

Relevant properties
The properties of the  service evaluated by the hyphenator are:

Changing the values of these properties in the Lingu-Properties affect all subsequent calls to the hyphenator.

A valid hyphenation position is a possible one that meets the restrictions given by the,   and   values.

For example, if  is 7, "remove" does not have a valid hyphenation position. Also, this is the case when  is 3 or   is 5.

The following example shows a word hypenated:

If the hyphenator implementation is working correctly, it reports a valid hyphenation position of 4 that is after the 'horse' part. Experiment with other values for nMaxLeading and other words. For example, if you set it to 4, no valid hyphenation position is found since there is no hyphenation position in the word 'horseback' before and including the 's'.

For a description of the return types interface, refer to com.sun.star.linguistic2.XHyphenatedWord.

The example below shows querying for an alternative spelling. In some languages, for example German in the old (pre-reform) spelling, there are words where the spelling of changes when they are hyphenated at specific positions. To inquire about the existence of alternative spellings, the  function is used:

The return types interface is the same as in the above example ( com.sun.star.linguistic2.XHyphenatedWord ).

The next example demonstrates getting possible hyphenation positions. To determine all possible hyphenation positions in a word, do this:

For a description of the return types interface, refer to com.sun.star.linguistic2.XPossibleHyphens.

Using Thesaurus
The interface used for the thesaurus is com.sun.star.linguistic2.XThesaurus. Accessing the thesaurus through the  and initializing the   object is done by:

The properties of the  service evaluated by the thesaurus are:

Changing the values of these properties in the  affect all subsequent calls to the thesaurus. The following example about retrieving synonyms shows this:

The reason to subdivide synonyms into different meanings is because there are different synonyms for some words that are not even closely related. For example, the word 'house' has the synonyms 'home', 'place', 'dwelling', 'family', 'clan', 'kindred', 'room', 'board', and 'put up'.

The first three in the above list have the meaning of 'building where one lives' where the next three mean that of 'a group of people sharing common ancestry' and the last three means that of 'to provide with lodging'. Thus, having meanings is a way to group large sets of synonyms into smaller ones with approximately the same definition.

Events
There are several types of events. For example, all user dictionaries com.sun.star.linguistic2.XDictionary report their status changes as events com.sun.star.linguistic2.DictionaryEvent to the, which collects and transforms their information into   events com.sun.star.linguistic2.DictionaryListEvent , and passes those on to its own listeners.

Thus, it is possible to register to the  as a listener to be informed about relevant changes in the dictionaries. There is no need to register as a listener for each dictionary.

The spell checker and hyphenator implementations monitor the changes in the  for changes of their relevant properties. If such a property changes its value, the implementation launches an event com.sun.star.linguistic2.LinguServiceEvent that hints to its listeners that spelling or hyphenation should be reevaluated. For this purpose, those implementations support the com.sun.star.linguistic2.XLinguServiceEventBroadcaster interface.

The  acts as a listener for com.sun.star.linguistic2.DictionaryListEvent and com.sun.star.linguistic2.LinguServiceEvent events. The respective interfaces are com.sun.star.linguistic2.XDictionaryListEventListener and com.sun.star.linguistic2.XLinguServiceEventListener. The events from the DictionaryList are transformed into com.sun.star.linguistic2.LinguServiceEvent events and passed to the listeners of the, along with the received events from the spell checkers and hyphenators.

Therefore, a client that wants to be notified when spell checking or hyphenation changes, for example, when it features automatic spell checking or automatic hyphenation, needs to be registered as com.sun.star.linguistic2.XLinguServiceEventListener to the  only.

Implementing the com.sun.star.linguistic2.XLinguServiceEventListener interface is similar to the following snippet:

After the client has been instantiated, it needs to register as com.sun.star.linguistic2.XLinguServiceEventListener. For the sample client above, this looks like:

This enables the sample client to receive com.sun.star.linguistic2.LinguServiceEvent s and act accordingly. Before the sample client terminates, it has to stop listening for events from the :

In the LinguisticExamples.java sample, a property is modified for the listener to be called.

Implementing a Spell Checker
A sample implementation of a spell checker is found in the examples for linguistics.

The spell checker implements the following interfaces:


 * com.sun.star.linguistic2.XSpellChecker
 * com.sun.star.linguistic2.XLinguServiceEventBroadcaster
 * com.sun.star.lang.XInitialization
 * com.sun.star.lang.XServiceDisplayName
 * com.sun.star.lang.XServiceInfo
 * com.sun.star.lang.XComponent

and


 * com.sun.star.lang.XTypeProvider, to access your add-in interfaces from LibreOffice Basic, otherwise, this interface is not mandatory.

To implement a spell checker of your own, modify the sample in the following ways:

Choose a unique service implementation name to distinguish your service implementation from any other. To do this, edit the string in the line

Then, specify the list of languages supported by your service. Edit the

function and modify the

function accordingly. The next step is to change the

as required. This function determines if a word is spelled correctly in a given language. If the word is OK return -1, otherwise return an appropriate value of the type com.sun.star.linguistic2.SpellFailure.

Check if you need to edit or remove the

and

functions. Consider this only if you are planning to support non-western languages and need sophisticated versions of those, or do not need them at all. Do not forget to change the code at the end of

accordingly.

Supply your own version of

It provides the return value for the

function call if the word was found to be incorrect. The main purpose is to provide proposals for how the word might be written correctly. Note the list may be empty.

Next, edit the text in

It should be unique but it is not necessary. If you are developing a set of services, that is, spellchecker, hyphenator and thesaurus, it should be the same for all of them. This text is displayed in dialogs to show a more meaningful text than the service implementation name.

Now, have a look in the constructor

at the property names. Remove the entries for the properties that are not relevant to your service implementation. If you make modification, also look in the file PropChgHelper_Spell.java in the function

and change it accordingly.

Set the values of  and   to true only for those properties that are relevant to your implementation, thus avoiding sending unnecessary com.sun.star.linguistic2.LinguServiceEvent events, that is, avoid triggering spell-checking in clients if there is no requirement.

Finally, after registration of the service (see Deployment Options for Components) it has to be activated to be used by the. After restarting LibreOffice, this is done in the following manner:

Open the dialog. In the section Writing Aids, in the box Available Language Modules, a new entry with text of the Service Display Name that you chose is displayed in the implementation. Check the empty checkbox to the left of that entry. If you want to use your module, uncheck any other listed entry. If you want to make more specific settings per language, press the button next to the modules box and use that dialog.

The Context menu of the Writer that pops up when pressing the right-mouse button over an incorrectly spelled word currently has a bug that may crash the program when the Java implementation of a spell checker is used. The spell check dialog is functioning.

Implementing a Hyphenator
A sample implementation of a hyphenator is found in the examples for linguistic.

The hyphenator implements the following interfaces:


 * com.sun.star.linguistic2.XHyphenator
 * com.sun.star.linguistic2.XLinguServiceEventBroadcaster
 * com.sun.star.lang.XInitialization
 * com.sun.star.lang.XServiceDisplayName
 * com.sun.star.lang.XServiceInfo
 * com.sun.star.lang.XComponent

and


 * com.sun.star.lang.XTypeProvider, if you want to access your add-in interfaces from LibreOffice Basic, otherwise, this interface is not mandatory.

Aside from choosing a new service implementation name, the process of implementing the hyphenator is the same as implementing the spell checker, except that you need to implement the com.sun.star.linguistic2.XHyphenator interface instead of the com.sun.star.linguistic2.XSpellChecker interface.

You can choose a different set of languages to be supported. When editing the sample code, modify the  and   methods to reflect the set of languages your implementation supports.

To implement the com.sun.star.linguistic2.XHyphenator interface, modify the functions

in the sample hyphenator source file at the stated positions.

Look in the constructor

at the relevant properties and modify the

function accordingly.

The rest, registration and activation is again the same as for the spell checker.

Implementing a Thesaurus
A sample implementation of a thesaurus is found in the examples for linguistic.

The thesaurus implements the following interfaces:


 * com.sun.star.linguistic2.XThesaurus
 * com.sun.star.lang.XInitialization
 * com.sun.star.lang.XServiceDisplayName
 * com.sun.star.lang.XServiceInfo
 * com.sun.star.lang.XComponent

and


 * com.sun.star.lang.XTypeProvider, if you want to access your add-in interfaces from LibreOffice Basic, otherwise, this interface is not mandatory.

For the implementation of the thesaurus, modify the sample thesaurus by following the same procedure as for the spell checker and thesaurus:

Choose a different implementation name for the service and modify the

and

functions.

The only function to be modified at the stated position to implement the com.sun.star.linguistic2.XThesaurus interface is

Look in the constructor

to see if there are properties you do not require.

Registration and activation is the same as for the spell checker and hyphenator.

Integrating Import and Export Filters
LibreOffice provides several implementations for objects that can be displayed in a task window. In the context of the Component Framework they are called Office Components. These components can be created from a content, e.g. stored in a file on disk. Most of the time this will be done by creating a document and loading the content into it using a filter. This section explains the implementation of LibreOffice import and export filter components. LibreOffice also allows to load content into a component directly by using a frame loader, but this is described in this section only briefly.

Introduction
Inside LibreOffice a document is represented by its document service, called model. For a list of available document services, refer to the section Document Specific Features. On disk, the same document is represented as a file or possibly as a dynamically generated output, for example, of a database statement. To generalize this and abstract from single disk files we just call it "content". The content is a serialization of a model, e.g. the ODF or the Word model. A filter component is used to convert between this model and the internal model defined by the document core model as shown in the following diagram.



In our API the three entities in the above diagram, content, model, and filter, are defined as UNO services. The services consist of several interfaces that map to a specific implementation, for example, using C++ or Java.

The filter implementer has to develop a class that implements the com.sun.star.document.ExportFilter or com.sun.star.document.ImportFilter service, or both in case the filter should support import and export. The filter will get a com.sun.star.document.MediaDescriptor that defines the stream the filter must use for its input or output.

Approaches
To implement said filter class, a developer can


 * link against the application core
 * use the document API
 * use the XML based techniques (sax or xslt)

Each method has unique advantages and disadvantages, that are summarized briefly:

Using the core data structure and linking against the application core is the way how all elder filters (originating from the "pre-UNO" area) are implemented in LibreOffice. As the disadvantages are huge (maintenance nightmare when core data structures or interfaces change), this approach is not recommended for new filter development in general.

Using the LibreOffice API based on UNO is more advantageous, since it solves the technical problems indicated in the above paragraph. The idea is to read data from a file on loading and build up a document using the LibreOffice API, and to iterate over a document model and write the corresponding data to a file on storing. The UNO component technology insulates the filter from binary layout, and other compiler and version dependent issues. Additionally, the API is expected to be more stable than the core interfaces, and provides an abstraction from the core applications. The developer creating an API based filter will directly provide a filter class implementing the service com.sun.star.document.ImportFilter and/or com.sun.star.document.ExportFilter

The third is to import and export documents using the XML-based file format. UNO-based XML import and export components have all the advantages of the previous method, but they have the additional advantage that the filter logic builds upon the ODF model that is not bound to LibreOffice as the document API is and so theoretically can be used in other applications also (the filter logic, not the filter as a whole). A disadvantage may be that conversions based on the ODF format can become a little bit more complicated and also can be worse than conversions based on a document API if they require access to layout information in the source or the target format.

The developer creating an XML based filter will not directly provide a filter class but use a generic filter class provided by LibreOffice. This filter class is the XMLFilterAdaptor of the document it works on. The filter adaptor service expects an XML based importer or exporter UNO service to be provided by the developer. LibreOffice provides generic importer and exporter services that allow to plug in a xslt to carry out a transformation that the importer or exporter feeds into the XMLFilterAdaptor.

In addition to the filter itself the developer must provide some information about it to enable LibreOffice to integrate it into the application framework. This information is provided as a configuration file. To understand better what needs to be in this file let's have a look on how LibreOffice deals with filters.

Checklist for filter developers
Integrating a filter into LibreOffice requires the following steps that will be explained in the following sections:


 * 1) Implement a filter (required).
 * 2) Implement an com.sun.star.document.ExtendedTypeDetection service to support detection by content (optional).
 * 3) Implement a filter options dialog if the implemented filter requires additional parameters (optional).
 * 4) Register the component libraries as UNO services (required). If the filter is deployed as an extension this is a part of it. If the filter will become a part of the LibreOffice installation, the registration must be done as described in the chapter Deployment Options for Components.
 * 5) Add configuration information to the org.openoffice.TypeDetection node of the configuration (required). If the filter is deployed as an extension, the extension will contain a configuration file. LibreOffice will access it as part of the extensions layer of the Configuration Manager. If the filter will become a part of the LibreOffice installation, the configuration must be integrated into the build process.

It is recommended to read the following chapters before carrying out any of these steps.

Filtering Process
In LibreOffice the whole process of loading or saving content is a modular system based on UNO services. Some of them are abstract (like e.g. the com.sun.star.document.ExtendedTypeDetection and the filter services) and so allow to bind extendable sets of instances implementing them, others (like e.g. the com.sun.star.document.TypeDetection service) are those that define the work flow. As they are exchangeable like any UNO service the whole process of finding and using filters can be changed without any need to change other involved components.

Loading content
The most general way to load content into LibreOffice is calling the com.sun.star.frame.XComponentLoader:loadComponentFromURL method of a suitable object. Such object may be the com.sun.star.frame.Desktop object or any instance of the com.sun.star.frame.Frame service. Content loaded this way will end up in a frame object always, if called at the desktop the method will find or create this frame using some of the passed arguments as described in the API documentation linked above. Then it will forward the call to this frame. Here's a diagram showing the workflow that will be explained in the following paragraphs.



The content will be passed to the  call as a com.sun.star.document.MediaDescriptor service that here is implemented as a Sequence of com.sun.star.beans.PropertyValue. In most cases it will contain several properties that allow to create an object implementing com.sun.star.io.XStream or com.sun.star.io.XInputStream that can be used to read the content. It also may contain some properties that the code of other objects (filter, model, controller, frame etc.) can use to steer the loading process. If no properties shall be handed over and the file content is specified by a URL only, the URL can be passed as an explicit argument and the MediaDescriptor can stay empty. To understand how to work with the MediaDescriptor in the implementation of a filter or elsewhere, especially how to retrieve a stream from it, see the documentation of it in the chapter about loading documents.

The component loader uses instances of the com.sun.star.frame.FrameLoader or com.sun.star.frame.SynchronousFrameLoader services. Which frame loader instance will be used depends on the type of the content. This type must be detected first (see below) based on the TypeDetection configuration that allows to register filters or frame loaders for a particular type. LibreOffice has a generic Frame Loader service that is used when the detected type has no own frame loader registered but filters. If a custom frame loader is registered for a particular type, it's up to that implementation how the content loading process is carried out and if it uses filters or not. As the current topic is "filters", we will concentrate on the generic frame loader here.

To load content based on a filter first it must be detected which filter is the right one to use and which document type must be used for this filter to work properly. As basically any content type may be loaded into any available document type and even the same type could be loaded into the same document type in different ways, we could find many registered filters for a particular content type. Finding the right one by evaluating what is passed in the MediaDescriptor is the job of the com.sun.star.document.TypeDetection service. The result of this detection will be the name of the content type, the name of the wanted filter and the service name of the document model that shall be the target of the loading process. These results will be placed into the MediaDescriptor so that any code in other objects called later can use that information. By providing either the type name of the content or the document service name in the MediaDescriptor handed over to the component loader the search for a filter can be narrowed down to a subset of filters that match these criteria. By providing a filter name in the MediaDescriptor the detection can even be bypassed completely (the component loader will add the matching type and document service names to the MediaDescriptor though). As the whole process of the Type Detection is completely based on the configuration, it will be described in the chapter about the TypeDetection configuration.

The next steps will be managed by the generic com.sun.star.frame.SynchronousFrameLoader service and hands the target frame over to it. The Frame Loader will create the document of the wanted type using the document service name found in the MediaDescriptor. It will also take the detected filter name and ask the com.sun.star.document.FilterFactory service to create the filter and perhaps initialize it with some necessary parameters and ask it for importing the content into the new document (this is described in the chapter about filters). If all of this went fine, it will attach the document to the target frame by creating a Controller object for the document model.

Storing content
A MediaDescriptor is passed to  or   in the interface com.sun.star.frame.XStorable, implemented by office documents. It will contain several properties that allow to create an object implementing com.sun.star.io.XStream or com.sun.star.io.XOutputStream that can be used to store the content. It also may contain some properties that give more information about how the storing process should be done. If no properties shall be handed over and the target file is specified by a URL only, the URL can be passed as an explicit argument and the MediaDescriptor can stay empty. To understand how to work with the MediaDescriptor in the implementation of a filter or elsewhere, especially how to retrieve a stream from it, see the documentation about it in the chapter about loading documents.

If the MediaDescriptor contains a type name or a filter name, the suitable export filter will be created using the. If neither of them is provided, the document will be stored with the latest ODF filter.

Filters
As described in the previous chapter, filters are objects that can be used to import or export content into or from LibreOffice documents. The API defines the two services com.sun.star.document.ImportFilter and com.sun.star.document.ExportFilter. A filter implementation can support one or both of them. If a particular filter that only supports import is used, the imported document is modified by the user and then the user presses the "Save" button, a "Save As" operation will be carried out instead as LibreOffice must assume that the filter component is "import only" and so storing must be done in a different format. It doesn't help to have a different export filter for the same content. If a direct "Save" operation should be possible, both filter services must be supported at the same filter object.

A filter is created from the factory service com.sun.star.document.FilterFactory. This service also provides a low-level access to the configuration that knows all registered filters of LibreOffice and their properties, supports search and query functionality, and creates and initializes filter components. As an example, if the type name of a content is known, a query at the FilterFactory can be used to retrieve one or more internal filter names of possible filters and after choosing one of them the filter can be created using this name.

Filters can be initialized if they implement the interface com.sun.star.lang.XInitialization. The method  is used by the filter factory service directly after creation of the filter object, before the filter is returned to the code that requested the filter. It passes the configuration data of the filter and all parameters and options that have been specified by the creation request to the factory. These properties usually originate from the "FilterOptions" property of the MediaDescriptor and have been put there either by the code requesting the loading or storing or by user input in a filter options dialog. How such filter dialog can be implemented is explained in the chapter about filter options.

The parameter list of  uses the following protocol:


 * The first item in the list is a sequence of com.sun.star.beans.PropertyValue structs, that describe the configuration properties of the filter.
 * All other items are directly copied from the parameter Arguments of the factory interface method com.sun.star.lang.XMultiServiceFactory:createInstanceWithArguments.

The fact that a filter gets its own name passed as an argument can be used to use one filter implementation to act as several filters in the configuration. This is shown in the following code snippet of the implementation of a filter initialization:

In one single workflow filters can act as an import or an export filter. If content is loaded, the creator of the filter will use the com.sun.star.document.XImporter interface and its method  to bind the filter to the document it should import into. If content is stored, the interface com.sun.star.document.XExporter and its method  will bind the filter to the document it shall get data from. The filtering process is done by the same method in both cases: it's the  method of the com.sun.star.document.XFilter interface that both kinds of filters must support. Here the  is passed to the filter.

This example code shows how the required filter operation can be tracked inside the filter implementation easily:

Structure of the configuration
As described previously, detecting types and finding filters in LibreOffice is carried out by the com.sun.star.document.TypeDetection service that uses configuration data as input. The configuration node that contains all this information is org.openoffice.TypeDetection. Here's the basic structure of it:



As shown on the left, the node consists of structures that in the terminology of the Configuration Manager are called sets. As opposed to configuration lists, sets are extendable configuration nodes and this allows the Configuration Manager to merge several files containing the same node together and presenting all set elements found in any of the merged files as part of a common set. This is different to lists: if the same list is found in several configuration files, one of them will overwrite the others. The ability to merge configuration nodes enables the deployment of filter configuration data (and so the deployment of filters) in extensions. Without it all filter configuration data had to be defined in the LibreOffice installation.

There are three lists: types, filters and frame loaders. A type describes a content, while filters or frame loaders describe objects that can be used to load such content into an LibreOffice document. Arrows in the picture point to structures on the right side. They show the content (properties) of different list elements. Similar to 1:n relations in a database, every filter or frame loader is registered for one or multiple types.

TypeDetection
Before the properties of types, filters and frame loaders will be described in close detail, let's have a look on how the Type Detection uses them to detect types and filters. The com.sun.star.document.TypeDetection service can be used to just detect the type of a particular content. While a type is detected, it is possible that some information about a possible filter for that type already may have accrued. In case the TypeDetection is part of a loading process where not only a type but also a filter needs to be detected, this suggestion can be used to save an extra filter detection step. This detection otherwise had to be carried out by the generic frame loader by accessing the filter configuration data through the com.sun.star.document.FilterFactory service.

When the TypeDetection receives a URL or a MediaDescriptor, it will first check some "external" attributes of the content specified this way. This could be a file extension, a URL pattern or other properties in the MediaDescriptor. If the MediaDescriptor does not already contain the name of the content type, the best match of the data in the "Types" part of the TypeDetection configuration to these attributes is sought. See the chapter about the type properties what kind of attributes are available and how they are used.

If a type has been detected based on these attributes, LibreOffice can verify this detection based on real code that checks the content, not only its external attributes. For this purpose each type may have an attribute "DetectService". It is an implementation or service name of an object that implements the abstract service com.sun.star.document.ExtendedTypeDetection. This object will examine the content. It will get a MediaDescriptor containing the name of the type to confirm and it will return this name in case it matches the content. It is allowed to return another type name if the DetectService knows that this type matches better even if the external attributes may not have selected it in the first place.

If the external attributes didn't help LibreOffice to find a type, it will instantiate all registered DetectServices and ask them to check the content until any of them returns a valid type name. The called DetectService can detect that it is called for "guessing", not for confirmation as in this case no type name is passed to it in the MediaDescriptor.

The next step is to check if a frame loader is registered for the detected type. If no frame loader is found, the generic frame loader implementation of LibreOffice is used. As mentioned above, this service will detect a filter in case the TypeDetection service not already has given this information. This detection is easily done by using a filter query at the com.sun.star.document.FilterFactory service. This query encapsulates the algorithm how LibreOffice assigns a filter to a type. The result of this query will be the internal filter name of the desired filter and the FilterFactory then can be asked to create the filter. Note: filter queries can return more than one filter name, depending on the input. If no preferences have been given, the first one in the returned sequence will win.

The most important external attribute of a content is a file extension and often just this one is used. As these extensions don't need to be unique, LibreOffice may find several possible types for an extension. While there is a preferred type (or at least there should be one), it is possible for API programmers to override this by a type preselection. It is also possible to use a filter preselection or a document type preselection. The latter can be seen as a suggestion to LibreOffice to load a content with a particular LibreOffice application. If this is possible, LibreOffice will do that, otherwise it will proceed as usual. One of the most common use cases is to load a html file by Calc from the command line. By using "soffice -Calc $FILENAME" instead of just "soffice $FILENAME" a document type preselection is triggered.

Properties of a Type
Every type inside LibreOffice is specified by the properties shown in the table below. These values are accessible at the previously mentioned service com.sun.star.document.TypeDetection using the interface com.sun.star.container.XNameAccess. Write access is not available here. All types are addressed by their internal names. The property names are identical to the configuration property names.

Properties of a Filter
Every filter inside LibreOffice is specified by the properties shown in the table below. These values are accessible at the previously mentioned service com.sun.star.document.FilterFactory using the interface com.sun.star.container.XNameAccess. Write access is not available here. All types are addressed by their internal names. The property names are identical to the configuration property names.

A filter always is registered for only one type. A single filter implementation can handle several types but then must be registered multiple times. One type may handled by more than one filter.

Sample configuration for an xslt based filter
Here the XMLFilter used is the com.sun.star.documentconversion.XSLTFilter that bridges to xslt files and basically can import and export if a suitable xslt is provided. It expects the following parameters in the user data ($(APP) stands for Writer,Calc,Draw,Impress,Chart,Math):

(1) service name of the XSLTFilter (3) implementation/service name of an importer class (com.sun.star.comp.$(APP).XMLOasisImporter) (4) implementation/service name of an exporter class (com.sun.star.comp.$(APP).XMLOasisExporter) (5) relative or absolute path name to an importing style sheet (6) relative or absolute path name to an importing style sheet

Filter Options
A filter may need some additional information before it can import or export properly. As an example, the LibreOffice filter " " needs a separator used to detect columns. This information is transported as a property  inside the. The value depends on the filter implementation and is not specified (type ). It's up to the filter to deal with it and handle it properly. The MediaDescriptor may contain another property of type string named. It can be used if the flexibility of an any is not required and the small overhead to retrieve the string from the any is unwanted. The filter must document which of these properties it uses and how the information transported by it must be shaped.

There are two possible origins of the FilterData or FilterOptions property:


 * The loading or storing process is triggered from code that has the necessary information and provides it in the code.
 * A user has entered the data into a dialog that LibreOffice has presented to him and retrieved it from the dialog after the user closed it. The dialog is shown by a UNO service that is specified by the  property of the filter configuration. LibreOffice will not show the dialog if the MediaDescriptor already contains one of the named properties.

The service specified by the  property is the only way how a filter can retrieve parameters interactively. The filter code itself must not do that because it may be used in an environment that does not allow to show any UI elements, especially modal ones. Here providing filter options by API calls is the only way to provide them to the filter.

The UIComponent is an object implementing the com.sun.star.ui.dialogs.FilterOptionsDialog. It will be called in a modal way, means with an  call that must guarantee that when it returns, all parameters can be retrieved from the UIComponent by its interface com.sun.star.beans.XPropertyAccess. The same interface is used to transfer the current  to the UIComponent before executing it. In the  call the implementer can use any UI elements, usually a dialog will be used here. The UIComponent must provide the filter options with the correct property names and the value of the property must be as the filter implementation understands it. The framework code will copy the retrieved properties to the  without any change.

If a filter doesn't get any FilterOptions or FilterData though it needs some, it may use default values for them, if possible. Usually this is always possible for export filters, but not always for import filters. The filter implementation should use a configuration file to retrieve default values instead of providing them in the code, so that they can be changed easily. Whether the filter updates the configuration values to the last recently used values passed by  or if it never changes them itself is up to the filter developer.

Properties of a FrameLoader
LibreOffice knows asynchronous ( com.sun.star.frame.FrameLoader ) and synchronous ( com.sun.star.frame.SynchronousFrameLoader ) frame loader implementations. They are not distinguished by the configuration data but detected at runtime, synchronous loaders are preferred.

When a document is loaded using a  call, a frame loader will always be used to load the "component" (in most cases a document model) into a frame. If no frame is registered for the type to be loaded, the generic frame loader of LibreOffice will be used that will proceed with selecting a filter and using it. Custom frame loaders are not obliged to use filters and can do anything else instead. An expected use case is when the component isn't a model but e.g. a controller or window object.

Every FrameLoader inside LibreOffice is specified by the properties shown in the table below. These values are accessible at the service com.sun.star.frame.FrameLoaderFactory using the interface com.sun.star.container.XNameAccess. Write access is not available here. All types are addressed by their internal names. The property names are identical to the configuration property names.

Document API Filter Development
TBD: Examples.

Introduction
This chapter outlines the development of XML based filtering components that use the XML filter adaptor framework. Further information is also available at https://www.openoffice.org/xml/filter/. The XML filter adaptor is a generic com.sun.star.document.XFilter implementation. It has been designed to be reusable, and to supply a standard method of designing and referencing XML based import and export filters. The XML filter adaptor does not perform any of the filtering functionality itself, but instead is used to instantiate a filtering component.

The advantage of the XML filter adapter framework is that you do not have to work with document models to create a document from an import file, nor do you have to iterate over a document model to export it to a different file format. Rather, you can use the LibreOffice XML file format to import and export. When importing, you parse your import file and send LibreOffice XML to the filter adaptor, which creates a document for you in the GUI. When exporting, the office sends a description of the current document as LibreOffice XML, so that you can export without having to iterate over a document model.

As described in the chapter about filters a filter works through its method. In case of XML based filters this method is implemented by the XML filter adaptor. Based on its "UserData" property it instantiates an XML import filter and uses its method com.sun.star.xml.XImportFilter:importer to pass a MediaDescriptor for the source, a specialized XML document handler for LibreOffice XML, and user data. The import filter must read the import source and deliver LibreOffice XML to the document handler received in the call to, emulating a SAX parser that calls the parser callback functions.

In case of export filters the same  call will use the "UserData" property to instantiate an XML export filter and use its method com.sun.star.xml.XExportFilter:exporter  to pass a target location and user data. In this case, the office expects the export filter to be a com.sun.star.xml.sax.XDocumentHandler, which is able to handle LibreOffice XML. The office creates an export stream with LibreOffice XML, and parses this XML so that the export filter receives the SAX callbacks and can translate them to whatever is necessary, writing the result to the target received in the call to com.sun.star.xml.XExportFilter:exporter.

Sample implementations
There are currently three filtering components which use the XML filter adapter.

The first one is the. This has been created as a means of linking the  Small Device filter framework with LibreOffice. This means that any available  plugin, can also be used as a LibreOffice filter. This is currently hosted within the  project in OpenOffice HG at

xmerge/java/org/openoffice/xmerge/xmergebridge

The final two are a Java and a C++ implementation of a Flat LibreOffice XML reader and writer. These are intended to be sample filter component implementations, and offer a skeleton filter component that can be expanded upon by developers wishing to create their own filtering components. These are temporarily hosted in HG at

xmerge/java/org/openoffice/xmerge/xmergebridge/FlatXml

Writing the Filtering Component
The filtering component must implement the following interfaces as described by the com.sun.star.xml.ImportFilter service and the com.sun.star.xml.ExportFilter service:

Importer:


 * com.sun.star.xml.XMLImportFilter

Exporter:


 * com.sun.star.xml.XMLExportFilter and com.sun.star.xml.sax.XDocumentHandler

XImportFilter
The service com.sun.star.xml.XMLImportFilter defines an interface with the following method:

is a, which can be used to obtain the following information:


 * An
 * This is a stream that is attached to the source to be read. This can be a file, or some other data source.


 * This is the name of the file on the disk, that the input stream comes from.
 * This is the name of the file on the disk, that the input stream comes from.


 * This is an URL describing the location being read.
 * This is an URL describing the location being read.

is a SAX event handler that can be used when parsing an, which may or may not contain LibreOffice XML. Before this stream can be read by LibreOffice, it will need to be transformed into LibreOffice XML.

is an array of, that contains the information supplied in the   section of the   definition in the TypeDetection.xcu file.

XExportFilter
The com.sun.star.xml.XExportFilter defines an interface with the following method:

and  contain the same type of information as in the importer, except that the   contains an , which can be used to write to.

XDocumentHandler
When the export takes place, the new Filtering component must also be an, to allow the output based on SAX events to be filtered, if required. For this reason, an  is not passed to the exporter, and any exporter that is used by the XML filter adaptor must implement the com.sun.star.xml.sax.XDocumentHandler interface.

Evaluating XImportFilter Parameters
The writing of an importer usually starts with extracting the required variables from the  and the. These variables are required for the filtering component to operate correctly. Depending on the requirements of the individual filter, the first thing to do is to extract the information from the, referred to as   in the interface definition. This can be achieved as follows:

Get the number of elements in the

Iterate through the  to find the information needed: an input stream, a file name, or a URL.

The  parameter passed to   contains information that defines how the filter operates, so this information must be referenced as required.

Importer Filtering
An  implementation has now been obtained that contains all the information you want to process. From the filtering perspective, you can just read from this stream and carry out whatever processing is required in order for the input to be transformed into LibreOffice XML. Once this has been done, however, you need to write the result to where it can be parsed into LibreOffice's internal format. A  can be used to achieve this. A  is a form of buffer that can be written to and read from. For the com.sun.star.xml.XImportFilter:importer, read from the  that was extracted from the  , and once the filtering has taken place, write to a   that has been created. This  can be read from when it comes to parsing. This is how the  is created:

The  can be read from, and the   can be written to.

Parsing the Result
Once the desired LibreOffice XML has been produced and written to the  of the , the   of the   can be parsed with the aid of the.

Assuming that the XML was valid, no exceptions will be thrown and the importer will return true. At this stage, the filtering is complete and the imported document will be displayed.

Evaluating XExportFilter Parameters
The com.sun.star.xml.XExportFilter:exporter method operates in much the same way as com.sun.star.xml.XImportFilter:importer, except that instead of the exporter using a provided  , it is itself a com.sun.star.xml.sax.XDocumentHandler implementation.

When the  method is invoked, the necessary variables need to be extracted for use by the filter. This is the same thing that happens with the importer, except that the  contains an , instead of the importer's. Once the variables have been extracted (and - in some cases - a  has been created) the   method returns. It does not carry out the filtering at this stage.

Exporter Filtering
After the com.sun.star.xml.XExportFilter:exporter method returns, the XML filter adapter then invokes the com.sun.star.xml.sax.XDocumentHandler methods to parse the XML output.

For the filtering, the com.sun.star.xml.sax.XDocumentHandler implementation is used. This consists of a set of SAX event handling methods, which define how particular XML tags are handled. These methods are:

The result of this event handling can be processed and written to the  that was extracted from the.

XML Filter Detection
The number of XML files that conform to differing DTD specifications means that a single filter and file type definition is insufficient to handle all of the possible formats available. In order to allow LibreOffice to handle multiple filter definitions and implementations, it is necessary to implement an additional filter detection module that is capable of determining the type of XML file being read, based on its  declaration.

To accomplish this, a filter detection service com.sun.star.document.ExtendedTypeDetection can be implemented, which is capable of handling and distinguishing between many different XML based file formats. This type of service supersedes the basic flat detection, which uses the file's suffix to determine the Type, and instead, carries out a deep detection which uses the file's internal structure and content to detect its true type.

Requirements for Deep Detection
There are three requirements for implementing a deep detection module that is capable of identifying one or more unique XML types. These include:


 * An extended type definition for describing the format in more detail (TypeDetection.xcu).
 * A  implementation.
 * A  definition (TypeDetection.xcu).

Extending the File Type Definition
Since many different XML files can conform to different DTDs, the type definition of a particular XML file needs to be extended. To do this, some or all of the  information can be contained as part of the file type definition. This information is held as part of the  property of the type node. A unique namespace or preface identifies the string at this point in the sequence as being a  declaration.

Sample Type definition:

The ExtendedTypeDetection Service Implementation
In order for the type detection code to function as an  service, you must implement the   method as defined by the com.sun.star.document.XExtendedFilterDetection interface definition:

This method supplies you with a sequence of s from which you can use to extract the current   and the   of the file being loaded:

Once you have the URL of the file, you can then use it to create a  from which you can open an   to the file:

You can now use this  to read the header of the file being loaded. Because the exact location of the  information within the file is not known, the first 1000 bytes of information will be read:

Once you have this information, you can start looking for a type that describes the file being loaded. In order to do this, you need to get a list of the types currently supported:

For each of these types, you must first determine whether the  property contains a DocType:

All the possible  declarations of the file types can be checked to determine a match. If a match is found, the type corresponding to the match is returned. If no match is found, an empty string is returned. This will force LibreOffice into flat detection mode.

TypeDetection.xcu DetectServices Entry
Now that you have created the  service implementation, you need to tell LibreOffice when to use this service.

First create a  node, unless one already exists, and then add the information specific to the detection service that has been implemented, that is, the name of the service and the file types that use it.

Number Formats
Number formats are template strings consisting of format codes defining how numbers or text appear, for example, whether or not to display trailing zeros, group by thousands, separators, colors, and how many decimals are displayed. This does not include any font attributes, except for colors. They are found wherever number formats are applied, for example, on the Numbers tab of the dialog in spreadsheets.

Number formats are defined on the document level. A document displaying formatted values has a collection of number formats, each with a unique index key within that document. Identical formats are not necessarily represented by the same index key in different documents.

Managing Number Formats
Documents provide their formats through the interface com.sun.star.util.XNumberFormatsSupplier that has one method  that returns com.sun.star.util.NumberFormats. Using, developers can read and modify number formats in documents, and also add new formats.

You have to retrieve the  as a property at a few objects from their com.sun.star.beans.XPropertySet interface, for example, from data sources supporting the com.sun.star.sdb.DataSource service and from database connections supporting the service com.sun.star.sdb.DatabaseEnvironment, or com.sun.star.sdb.DatabaseAccess. In addition, all UNO controls offering the service com.sun.star.awt.UnoControlFormattedFieldModel have a  property.

NumberFormats Service
The com.sun.star.util.NumberFormats service specifies a container of number formats and implements the interfaces com.sun.star.util.XNumberFormatTypes and com.sun.star.util.XNumberFormats.

XNumberFormats
supports the interface com.sun.star.util.XNumberFormats. This interface provides access to the number formats of a container. It is used to query the properties of a number format by an index key, retrieve a list of available number format keys of a given type for a given locale, query the key for a user-defined format string, or add new format codes into the list or to remove formats.

The important methods are probably  and. The method  finds the key for a given format string and locale, whereas   creates a new format in the container and returns its key for immediate use. The  is reserved for future use and should be set to false.

The properties of a single number format are obtained by a call to  which returns a com.sun.star.util.NumberFormatProperties service for the given index key.

XNumberFormatTypes
The interface com.sun.star.util.XNumberFormatTypes offers functions to retrieve the index keys of specific predefined number format types. The predefined types are addressed by constants from com.sun.star.util.NumberFormat. The  contains values for predefined format types, such as PERCENT, TIME, CURRENCY, and TEXT.

In most cases you will need. It expects a type constant from the  group and the locale to use, and returns the key of the corresponding predefined format.

Applying Number Formats
To format numeric values, an  is attached to an instance of a com.sun.star.util.NumberFormatter, available at the global service manager. For this purpose, its main interface com.sun.star.util.XNumberFormatter has a method. When the  is attached, strings and numeric values are formatted using the methods of the. To specify the format to apply, you have to get the unique index key for one of the formats defined in. These keys are available at the  and   interface of.

Numbers in documents, such as in table cells, formulas, and text fields, are formatted by applying the format key to the  property of the appropriate element.

NumberFormatter Service
The service com.sun.star.util.NumberFormatter implements the interfaces com.sun.star.util.XNumberFormatter and com.sun.star.util.XNumberFormatPreviewer.

XNumberformatter
The interface com.sun.star.util.XNumberFormatter converts numbers to strings, or strings to numbers, or detects a number format matching a given string.

XNumberformatPreviewer
This interface com.sun.star.util.XNumberFormatPreviewer converts values to strings according to a given format code without inserting the format code into the underlying com.sun.star.util.NumberFormats collection.

The example below demonstrates the usage of these interfaces.

Document Events
Recurring actions, such as loading, printing or saving, that occur when working with documents, are document events, and all documents in LibreOffice offer an interface that sends notifications when these events take place.

There are general events common every document, such as loading, printing, or saving, and there are other events that are specific to a particular document type. Both can be accessed through the same interface.

In the document events API, these events are represented by an event name. The following table shows a list of all general document event names:

These event names are documented in the com.sun.star.document.Events service. Note that this service description exceeds the scope of events that happen on the document as a whole - so it also contains events that can only be accessed by finding the part of the document where the event occurred, for example, a button in a form. This list of events can also be extended by new events, so that future versions of LibreOffice can support new types of events through the same API. Therefore, every client that wants to deal with a particular document event must check if this event is supported, or whether it should be prepared to catch an exception.

Every client that is interested in document events can register for being notified. The necessary interface for notification is com.sun.star.document.XEventBroadcaster, which is an optional interface of the service com.sun.star.document.OfficeDocument. All document objects in LibreOffice implement this interface. It has two methods to add and remove listeners for document events:

The listeners must implement the interface com.sun.star.document.XEventListener and get a notification through a call of their method:

The argument of this call is a com.sun.star.document.EventObject struct, which is derived from the usual com.sun.star.lang.EventObject and contains two members: the member Source, which contains an interface pointer to the event source (here the com.sun.star.document.OfficeDocument service) and the member  which can be one of the names shown in the preceding table.

Both methods in the interface com.sun.star.document.XEventBroadcaster can cause problems in scripting languages if the object that implements this interface also implements com.sun.star.lang.XComponent, because it has two very similar methods:

Unfortunately this applies to all LibreOffice documents.

In C++ and Java this is no problem, because the complete signature of a method, including the arguments, is used to identify it.

In LibreOffice Basic, the fully qualified name including the interface can be used from OpenOffice.org 1.1.0:

But the OLE automation bridge, and possibly other scripting language bindings, are unable to distinguish between both  and   methods based on the method signature and must be told which interface you want to use.

You must use the core reflection to get access to either method. The following code shows an example in VBScript, which registers a document event listener at the current document.

The C++ code below uses OLE Automation. Two helper functions are provided that help to execute UNO operations.

Another way to react to document events is to bind a macro to it - a process called event binding. From OpenOffice.org 1.1.0 you can also use scripts in other languages, provided that a corresponding scripting framework implementation is present.

All document objects in LibreOffice support event binding through an interface com.sun.star.document.XEventsSupplier. This interface has only one method:

This method gives access to a container of event bindings. The container is represented by a com.sun.star.container.XNameReplace interface that, together with the methods of its base interfaces, offers the following methods:

Each container element represents an event binding. By default, all bindings are empty. The element names are the event names shown in the preceding table. In addition, there are document type-specific events. The method  yields all possible events that are supported by the object and   checks for the existence of a particular event.

For every supported event name you can use  to query for the current event binding or   to set a new one. Both methods may throw a com.sun.star.container.NoSuchElementException exception if an unsupported event name is used.

The type of an event binding, which is wrapped in the any returned by, is a sequence of com.sun.star.beans.PropertyValue that describes the event binding.

In OpenOffice.org 1.1.0 there is another important extension in the area of document events and event bindings. This version has a new service com.sun.star.frame.GlobalEventBroadcaster that offers the same document-event-related functionality as described previously (interfaces com.sun.star.document.XEventBroadcaster, com.sun.star.document.XEventsSupplier ), but it allows you to register for events that happen in any document and also allows you to set bindings for all documents that are stored in the global UI configuration of LibreOffice. Using this services frees you from registering at every single document that has been created or loaded.

Though a potential listener registers for event notifications at this global service and not at any document itself, the received event source in the event notification is the document, not the. The reason for this is that usually a listener contains code that works on the document, so it needs a reference to it.

The service com.sun.star.frame.GlobalEventBroadcaster also supports two more events that do not occur in any document but are useful for working with document events:

The event source in the notifications is NULL (empty).

All event bindings can be seen or set in the LibreOffice UI in the dialog on the Events page. Two radio buttons on the right side of the dialog toggle between LibreOffice and Document binding. In OpenOffice.org 1.1.0, you can still only bind to LibreOffice Basic macros in the dialog. Bindings to script: URLs can only be set using the API, but the dialog is at least able to display them. If, in OpenOffice.org 1.1.0, a global and a document binding are set for the same event, first the global and then the document binding is executed. With older versions, only the document binding was executed, and the global binding was only executed if no document binding was set.

Path Organization
The path settings service is the central service that manages the paths of LibreOffice. Almost every component inside LibreOffice uses one or more of the paths to access its resources located on the file system.

Users can customize most of the paths in LibreOffice by choosing.

Path Settings
The com.sun.star.util.PathSettings service supports a number of properties which store the LibreOffice predefined paths. There are two different groups of properties. One group stores only a single path and the other group stores two or more paths - separated by a semicolon.

Configuration
The path settings service uses the group Path in the org.Openoffice.Office.Common branch to read and store paths. The  and   groups in the share layer of the configuration branch store the path settings properties. The  group initialize the properties of the path settings service during startup. If the user activates the Default button in the path options dialog, the  group values are copied to the current ones.

Accessing Path Settings
The path settings service is a one-instance service that supports the com.sun.star.beans.XPropertySet, com.sun.star.beans.XFastPropertySet and com.sun.star.beans.XMultiPropertySet interfaces for access to the properties.

The service can be created using the service manager of LibreOffice and the service name com.sun.star.util.PathSettings. The following example creates the path settings service.

The main interface of the path settings service is com.sun.star.beans.XPropertySet. You can retrieve and write properties with this interface. It also supports getting information about the properties themselves.


 * The path settings service returns an  interface where more information about the path properties can be retrieved. The information includes the name of the property, a handle for faster access with , the type of the property value and attribute values.
 * The path settings service returns an  interface where more information about the path properties can be retrieved. The information includes the name of the property, a handle for faster access with , the type of the property value and attribute values.


 * This function can set the path properties to a new value. The path settings service expects that a value of type string is provided. The string must be a correctly encoded file URL. If the path property supports multiple paths, each path must be separated by a semicolon . Path variables are also allowed, so long as they can be resolved to a valid file URL.
 * This function can set the path properties to a new value. The path settings service expects that a value of type string is provided. The string must be a correctly encoded file URL. If the path property supports multiple paths, each path must be separated by a semicolon . Path variables are also allowed, so long as they can be resolved to a valid file URL.


 * This function retrieves the value of a path property. The property name must be provided and the path is returned. The path settings service always returns the path as a file URL. If the property value includes multiple paths, each path is separated by a semicolon.
 * This function retrieves the value of a path property. The property name must be provided and the path is returned. The path settings service always returns the path as a file URL. If the property value includes multiple paths, each path is separated by a semicolon.

The illustration below shows how the path settings, path substitution, and configuration service work together to read or write path properties.



The following code example uses the path settings service to retrieve and set the path properties.

Path Variables
Path variables are used as placeholders for system-dependent paths or parts of paths which are only known during the runtime of LibreOffice. The path substitution service com.sun.star.util.PathSubstitution - which manages all path variables of LibreOffice - checks the runtime environment during startup and sets the values of the path variables. The path substitution service supports a number of predefined path variables. They provide information about important paths that LibreOffice currently uses. They are implemented as read-only values and cannot be changed.

LibreOffice is a multi-platform solution that runs on different file systems. Obviously users want to have a single user configuration on all workstations across all platforms in a networked installation. For example, a user wants to use both the Windows and Unix version of LibreOffice. The home directory and the working directory are located on a central file server that uses Samba to provide access for Windows systems. The user only wants to have one user installation for both systems, so that individual settings only need to be specified once.

The path settings service described in Path Settings utilizes the path substitution service. In the configuration of LibreOffice, path variables describe the path settings, and these variables can be substituted by platform-specific paths during startup. That way, path substitution gives users the power to apply path settings only once, while the system takes care of the necessary platform-dependent and environment adaptations.

The illustration below shows how a path variable can resolve the path problem that arises when you use the same user directory on different platforms.



The following sections describe predefined variables, how to define your own variables, and how to resolve path variables with respect to paths in your programs.

Predefined Variables
The path substitution service supports a number of predefined path variables. They provide information about the paths that LibreOffice currently uses. They are implemented as read-only values and cannot be modified.

The predefined path variables can be separated into three distinct groups. The first group of variables specifies a single path, the second group specifies a list of paths that are separated by the shell or operating system dependent character, and the third group specifies only a part of a path.

All predefined variable names are case insensitive, as opposed to the user-defined variables that are described below.

The values of $(lang), $(langid) and $(vlang) are based on the property ooLocale in the configuration branch org.openoffice.Setup/L10N, that is normally located in the share directory. This property follows the ISO 639-1/ISO3166 standards that define identification codes for languages and countries. The ooLocale property is written by the setup application during installation time. The following are examples of table Mapping ISO 639/3166 to $(vlang):

Syntax
The path substitution service supports the definition and usage of user-defined path variables. The variable names must use this syntax:

variable ::= "$(" letter { letter | digit } ")" letter ::= "A"-"Z"|"a"-"z" digit ::= "0"-"9"

The user-defined variables must be defined in the configuration branch org.openoffice.Office.Substitution. LibreOffice employs a rule-based system to evaluate which definition of a user-defined variable is chosen. The following sections describe the different parts of this rule-based system and the configuration settings that are required for defining new path variables.

Environment Values
To bind a specific value to a user-defined path variable, the path substitution service uses environment values. The path substitution service chooses a variable definition based on the values of these environment parameters. The following table describes which parameters can be used:

Rules
The user can define the mapping of environment parameter values to variable values. Each definition is called a rule and all rules for a particular variable are the rule set. You can only have one environment parameter value for each rule.

The following example rules specify that the user-defined variable called  is bound to the directory s:\develop\documentation if LibreOffice is running under Windows. The second rule binds  to /net/develop/documentation if LibreOffice is running under Solaris.

Variable name=devdoc Environment parameter=OS Value=file:///s:/develop/documentation

Variable name=devdoc Environment parameter=SOLARIS Value=file:///net/develop/documentation

Analyzing User-Defined Rules
LibreOffice uses matching rules to find the active rule inside a provided rule set.

The illustration below shows the analyzing and matching of user-defined rules.
 * 1) Tries to match with the Host environment parameter. If more than one rule matches - this can be possible if you use the asterisk (*) wildcard character - the first matching rule is applied.
 * 2) Tries to match with the different Domain parameters. There is no predefined order for the domain parameters - the first matching rule is applied.
 * 3) Try to match with the OS parameter. The specialized values have a higher priority than generic ones, for example, LINUX has a higher priority than UNIX.



The analyzing and matching process is done whenever a rule set has changed. Afterwards the values of the user-defined path variables are set and can be retrieved using the interface com.sun.star.util.XStringSubstitution.

Configuration
The path substitution service uses the org.openoffice.Office.Substitution configuration branch for the rule set definitions, which adhere to this schema:

The  set is the root container that store the definition of the different user-defined path variables. The  set uses nodes of type   which defines a single user-defined path variable.

A  set is a container for the different rules, called   in the configuration.

The following example uses two rules to map a Windows and Unix specific path to the user-defined path variable MyDocuments.

Resolving Path Variables
This section explains how to use the LibreOffice implementation of the path substitution service. The following code snippet creates a path substitution service.

The service is implemented as a one-instance service and supports the interface com.sun.star.util.XStringSubstitution. The interface has three methods:

The method  returns a string where all known variables are replaced by their value. Unknown variables are not replaced. The argument  can be used to indicate that the client needs a full substitution - otherwise the function fails and throws a com.sun.star.container.NoSuchElementException. For example: $(inst)/share/autotext/$(vlang) could be substituted to file:///c:/OpenOffice.org1.0.2/share/autotext/english.

The method  returns a string where parts of the provided path   are replaced by variables that represent this part of the path. If a matching variable is not found, the path is not modified.

The predefined variable  is not used for substitution. Instead, it is a placeholder for the path environment variable does not have a static value during runtime. The path variables,   and  , which represent a directory or a filename in a path, only match inside or at the end of a provided path. For example: english is not replaced by $(vlang), whereas file:///c:/english is replaced by file:///c:/$(vlang).

The method  returns the current value of the provided path variable as a predefined or a user-defined value. If an unknown variable name is provided, a com.sun.star.container.NoSuchElementException is thrown. The argument variable can be provided with preceding " " and succeeding " " or without them. So both $(work) and work can be used.

This code example shows how to access, substitute, and resubstitute path variables by means of the LibreOffice API.

Overview
Users of a client application that can communicate with a variety of services on a network may need to enter several passwords during a single session to access different services. This situation can be further exacerbated if the client application also requires the user to enter a password each time a particular network service is accessed during a session.

As most network users must authenticate to an OS at login time, it would make sense to access some required network services at this time as well. A solution to this problem is provided by the Single Sign-On (SSO) methodology, which is the ability to login in once and access several protected network services.

The best known SSO is the Kerberos network authentication protocol (see rfc1510). Kerberos functionality is commonly accessed through the Generic Security Service Application Program Interface (GSS-API, see rfc2743). Central to GSS-API is the concept of a security context, which is the "state of trust" that is initiated when a client (also known as source or initiator) identifies itself to a network service (also known as target or acceptor). If mutual authentication is supported, then the service can also authenticate itself to the client. To establish a security context, security tokens are exchanged, processed, and verified between the client and the service. The client always initiates this exchange. Once established, a security context can be used to encrypt or decrypt subsequent client-service communications.

The LibreOffice SSO API is based on GSS-API. The SSO API supports the creation of security contexts on the client and the service side as well as the generation of the security tokens that are required for the exchange to complete the security context based authentication. The SSO API does not support the actual exchange of security tokens or the encryption or decryption of client-service communications in an established security context.

LibreOffice implements SSO in two different ways to authenticate with an LDAP server for configuration purposes. The first is Kerberos based and the second is a simple non-standard "cached username/password" SSO. The latter is provided as a fallback to support scenarios where no Kerberos server is available.

Implementing the LibreOffice SSO API
Implementing the LibreOffice SSO API involves creating security context instances (see  and   below) and using these instances to create and process security tokens. All the LibreOffice SSO interfaces are available from the ::com::sun::star::auth namespace. The major interfaces are shown in Illustration 7.22 and described below.

XSSOManagerFactory
Represents the starting point for interaction with the SSO API. This interface is responsible for providing  (described below) instances based on the user's configured security mechanism e.g. "KERBEROS".

XSSOManager
This interface is responsible for the creation of not established security contexts for clients and services. An  instance "supports" a single security mechanism, that is, the context instances that are created by an   instance only interact with a single security mechanism implementation.

XSSOInitiatorContext
This interface represents a client-side security context that is not established when it is created. A single method,, is provided so that you can create an initial client-side security token that can be delivered to the relevant service and for processing or validating returned service-side security tokens (if mutual authentication is supported). The expected sequence of events for this client-side security context is:


 * The client calls, passes NULL as the parameter, receives an appropriate client-side security token in return.
 * The client sends the security token to the relevant service.
 * If the service successfully processes this token, the client is authenticated.
 * If mutual authentication is not supported, the client-side authentication sequence is now complete.
 * If mutual authentication is supported, the service sends a service-side security token to the client.
 * The client calls  a second time and passes the returned service-side security token as a parameter. If the token is successfully passed, the service is authenticated.

XSSOAcceptorContext
This interface represents a service-side security context that is not established when it is created. A single method,, is provided and is responsible for processing an initial client-side security token. If mutual authentication is supported, the method also generates a service-side security token for the client. The expected sequence of events for this service-side security context is:


 * The service receives the client-side security token.
 * The service calls, passes the client-side security token as a parameter, and if successful, the client is authenticated.
 * If mutual authentication is not supported, the service-side authentication sequence is now complete.
 * If mutual authentication is supported,  returns a non-zero length service-side security token.
 * The service sends the service-side security token to the client to authenticate the service.



The following example is a sample usage of the LibreOffice SSO API that provides the  method of the fictitious client--side   class. For simplicity, assume that  has the following members:


 * identifies a client-side user that needs to authenticate to a network service.
 * identifies the service to which the user needs to authenticate.
 * identifies the network host where the service of interest is running.

The SSO Password Cache
When you implement the SSO API, you may require access to user passwords, especially if you are relying on a preexisting underlying security mechanism. If you do not know how to gain such access, you can use the LibreOffice SSO password cache. This cache provides basic support for maintaining a list of username or password entries. Individual entries have a default lifetime corresponding to a single user session, but can optionally exist for multiple sessions. Support is provided for adding, retrieving, and deleting cache entries. Only one entry per username can exist in the cache at any time. If you add an entry for an existing username, the new entry replaces the original entry. The SSO password cache is represented by a single interface, namely the  interface, available in the.

RDF metadata
com.sun.star.rdf

ODF 1.2 introduces a new metadata mechanism based on RDF. RDF expands to Resource Description Framework, and is an W3C standard. Please refer to the W3C for information about RDF: https://www.w3.org/RDF/

Especially the first 2 sections of the RDF Primer are required reading for understanding the (really quite simple) basic concepts of the RDF data model: RDF Primer

If you like reading an in-depth specification, please refer to: RDF Concepts and Abstract Syntax

If you are interested in some motivational use cases, and an overview of the basic design from the ODF perspective, have a look at the ODF Metadata examples document.

The LibreOffice implementation of the RDF data model lives in the com.sun.star.rdf module.

Nodes
First, there are the basic RDF node types:

The interface com.sun.star.rdf.XResource is only necessary to separate the literal, which is not a resource, from the blank node and URI.

Literals
Literals are represented by the service com.sun.star.rdf.Literal.

This service has three constructors, one for every distinct kind of literal in RDF.

The simplest kind of literal is a plain value.

A literal may also have a data type, which is represented by an URI. Such literals are called typed literals. The W3C XMLSchema Part 2 specification contains several widely used data types such as numbers, booleans, dates, and many more.

It is also possible to create a literal with a specific language. This makes it possible to have a multi-lingual RDF graph, where statements are repeated with the same subject and predicate, but different objects that contain the same text content in different languages.

URIs
In RDF, URIs are used to denote resources. URIs may be used as subjects or objects of a statement. In contrast with other node types, URIs may also be used as the predicate of a statement.

The URI service has constructors com.sun.star.rdf.URI:create and com.sun.star.rdf.URI:createNS, which allow for creating an URI from a string. These two constructors are very similar, but  allows splitting the parameter into two parts, which may be useful when creating several URIs that share a prefix because they belong to the same vocabulary.

There are many URIs that are well-known because they are specified in various standards, such as XMLSchema datatypes, RDF concepts, OWL, and ODF.

There is a convenient way to construct such URIs: using the com.sun.star.rdf.URI:createKnown constructor, together with constants from the com.sun.star.rdf.URIs constant group.

Of course, string literals would be easier to use, but unfortunately UNO IDL does not permit them.

Blank nodes
The other kind of RDF node is the blank node, which is a resource, but in contrast to an URI, is not unique. Because blank nodes are not unique, you should only construct them with the com.sun.star.rdf.XRepository:createBlankNode method, not with the service constructor, and you should never use a blank node with a different repository than the one that created it.

Statements
Using these nodes, RDF statements can be constructed, which are basically subject-predicate-object triples.

The subject of the statement is the entity that the statement is about. The subject must be either an URI or a blank node; a literal is not allowed.

The predicate denotes what the relationship between the subject and the object is. In order to ensure that statements have a machine-readable semantics, only URIs are allowed as predicates.

The object of the statement may be any kind of RDF node.

If you put many statements together, and these statements share subjects and objects, then you will get a RDF graph.

Graphs
Graphs are represented by the interface com.sun.star.rdf.XNamedGraph. As the name implies, a named graph has a name, which is a URI. This is why the com.sun.star.rdf.XNamedGraph interface inherits from com.sun.star.rdf.XURI.

The individual methods will be discussed in subsequent sections. There is no service for a named graph, because named graphs always live in a repository.

Repository
The repository is the centerpiece of the RDF API. It is defined in the interface com.sun.star.rdf.XRepository, and the service com.sun.star.rdf.Repository.

A RDF repository is basically a set of named RDF graphs. The names of the contained graphs can be retrieved via the com.sun.star.rdf.XRepository:getGraphNames method. An individual graph can be retrieved via the com.sun.star.rdf.XRepository:getGraph method.

A repository may be created as a stand-alone service, or it may be associated with a loaded ODF document. The graphs in a document repository correspond to streams in an ODF package, and thus the graph names consist of the URI of the ODF package and the relative path of the stream within the package.

Services that provide an RDF repository implement the interface com.sun.star.rdf.XRepositorySupplier.

Document integration
The other main part of the RDF API is the integration in document models. This purpose is served by the interface com.sun.star.rdf.XDocumentMetadataAccess, which is implemented by the  service of documents.

Furthermore, there is the interface com.sun.star.rdf.XMetadatable, which allows document content entities to be used as subjects or objects in the methods that manipulate RDF graphs.

Annotated text range
The service com.sun.star.text.InContentMetadata allows to add annotations to a range of text. The range of text must be contained within a single paragraph, and annotations must not overlap (but they are allowed to nest).

When the  is successfully inserted, you can add metadata by just using it as the subject or object of an RDF statement.

Metadata field
There is a new text field that is explicitly designed for being used with RDF metadata: com.sun.star.text.textfield.MetadataField.

In contrast with the, where an existing range of text is being annotated with additional metadata, the metadata field allows for text content to be generated from RDF metadata.

For example, a bibliography extension could use a metadata field to insert a citation. The user could tell the bibliography extension which citation format should be used, and the extension will generate the content of all the citation metadata fields based on this choice. The extension may use some bibliography database that may also be stored as an RDF graph.

Metadata fields must be contained within a single paragraph, and must not overlap (but they are allowed to nest).

To enable generating the content, the metadata field implements the com.sun.star.text.XText interface.

Of course, you can not just insert plain text, but everything that you could insert into a paragraph.

Metadata fields have another interesting aspect: they can have a prefix and/or suffix text that is taken from one of the RDF graphs in the document. In this way you can create a metadata field with text content that is automatically displayed (non-editable) based on an RDF statement.

Finding in-content metadata at a cursor position
Assume you have a text cursor at some position, and you want to find out whether there is a annotated text range or a metadata field at the cursor position. For this purpose in OpenOffice.org 3.3 the property  was added to the text cursor in Writer. The following sample will retrieve the innermost nested text content at the current cursor position:

Because annotated text ranges and metadata fields may be nested, it may be the case that there are actually several such text contents at a given cursor position. In order to retrieve the outer nested text contents, use the com.sun.star.container.XChild interface of the  and   services (also added in OOo 3.3).

Other document entities
In addition to the annotated text range and the metadata field, other document content entities implement the com.sun.star.rdf.XMetadatable interface as well. These entities can thus be used in RDF statements. The list of entities which can be thus annotated will grow in future releases of LibreOffice.

Adding metadata to a document
The metadata support in ODF 1.2 allows for adding RDF graphs to an ODF package. Every RDF graph is stored as an  stream in the package.

There is a special RDF graph called the metadata manifest. This RDF graph belongs to a document and enumerates all the files relevant for metadata, such as the individual RDF/XML files.

This manifest graph is maintained by LibreOffice itself; extension authors should not modify it directly, but use the interface com.sun.star.rdf.XDocumentMetadataAccess.

In order to isolate different metadata users, every extension that wants to add metadata should create one (or several) own RDF graph(s). It is recommended to give the new graphs a type that identifies what kind of information is contained, especially if a well-known RDF vocabulary is used. With the method com.sun.star.rdf.XDocumentMetadataAccess:addMetadataFile, you can specify as many types as you want for a graph.

Now you can simply insert RDF statements into the graph:

Reading metadata from a document
In order to read metadata that is stored in a document, query the RDF repository of the document.

There are basically two ways to do this. One way is to use the getter methods at the named graph and repository interfaces. The method com.sun.star.rdf.XRepository:getStatements will return all statements in any graph in the repository that match the given parameters. But note that this is not necessarily what you want. Usually, an extension is only interested in the metadata it has itself inserted. Thus it is better to first get the graph(s) that the extension is interested in, and then only query those graphs via com.sun.star.rdf.XNamedGraph:getStatements.

The other way of getting information out of the repository is via the SPARQL query language.

The same considerations as above apply: by default, the result will contain information from all graphs in the repository. You can restrict the graphs via the  or   clauses.

Besides the  query shown above, there are also the methods com.sun.star.rdf.XRepository:querySelect, which returns a table of results, and com.sun.star.rdf.XRepository:queryAsk , which simply returns a. There are different methods for the different query types because the return types differ.

Mapping from URIs to document entities
Note that for a document content annotation the RDF repository will only give you an URI in its results, not the actual document content entity. In order to map the URI to the document entity, use the com.sun.star.rdf.XDocumentMetadataAccess:getElementByURI method.

Removing metadata from a document
The named graph supports the com.sun.star.rdf.XNamedGraph:removeStatements method, which removes all statements that match the parameters from the graph.

Also, there is the com.sun.star.rdf.XNamedGraph:clear method, which is equivalent to, and removes all statements from the graph.

For removing whole metadata streams from an ODF document, there is the method com.sun.star.rdf.XDocumentMetadataAccess:removeMetadataFile.

Vocabulary
Some notes on RDF vocabularies; of course, a comprehensive discussion of RDF design is beyond the scope of this guide.

An important question when adding RDF metadata is: which vocabulary do you use? First, it is usually a good idea to re-use an existing vocabulary. This will improve the chances that other software, which also supports the existing vocabulary, is able to do something interesting and useful with the metadata that is added.

For example, for basic datatypes you can use the types specified in W3C XMLSchema Part 2. A well-known vocabulary for expressing social relations is Friend-of-a-Friend. A directory of RDF schemata can be found at SchemaWeb. Another useful resource might be DBPedia.

If you do not find an existing vocabulary that matches your use case, here are some hints for designing your own: The most important thing is that the URIs should really be unique. If you have a DNS domain, then that is quite easy to achieve: use URIs like. It is probably a good idea to use a versioned namespace prefix like  for all URIs. The version component allows you to evolve the vocabulary to meet future requirements. Now you can use the versioned namespace prefix to denote the format, i.e., as a type for your metadata stream, making it easy to find. You can also create an actual HTML page to document the vocabulary at the URI.

Status
As of Openoffice.org version 3.2, RDF metadata is only supported in Writer documents. The generic RDF parts of the API are all implemented. The document integration parts are not yet completely implemented: most elements do not support the  that is required for use with RDF. In OOo version 3.3, support for more elements was added. The following elements can be annotated:

Jump Lists
com.sun.star.system.windows

Jump Lists is a Windows feature which adds shortcuts to the application menu in the task bar. By default, LibreOffice shows the recently added and often used documents there.

With the Jump List UNO API you can customize what is shown in the Jump List and add you own shortcuts.

There are four groups which can be shown in the Jump List:
 * Recent documents
 * Frequent documents
 * Tasks (Shortcuts to application features)
 * Custom categories

The following BASIC example adds a custom category, some tasks and shows the recent and frequent documents.