Services

From Apache OpenOffice Wiki
Jump to: navigation, search



We have seen that a single-inheritance interface describes only one aspect of an object. However, it is quite common that objects have more than one aspect. UNO uses multiple-inheritance interfaces and services to specify complete objects which can have many aspects.

Apache OpenOffice objects can inherit services, including interfaces, from only one parent object. However, objects can implement multiple interfaces. Inherited methods can be provided by the parent of the object; implemented methods must be provided by the object itself. Although Apache OpenOffice does not support true multiple-inheritance, objects can implement multiple interfaces, which gives them the appearance of having inherited methods from several other objects. When the term multiple-inheritance interface is used in Apache OpenOffice, it actually refers to multiple interface implementation.

In a first step, all the various aspects of an object (which are typically represented by single-inheritance interfaces) are grouped together in one multiple-inheritance interface type. If such an object is obtainable by calling specific factory methods, this step is all that is needed. The factory methods are specified to return values of the given, multiple-inheritance interface type. If, however, such an object is available as a general service at the global component context, a service description must be provided in a second step. This service description will be of the new style, mapping the service name (under which the service is available at the component context) to the given, multiple-inheritance interface type.

For backward compatibility, there are also old-style services, which comprise a set of single-inheritance interfaces and properties that are needed to support a certain functionality. Such a service can include other old-style services as well. The main drawback of an old-style service is that it is unclear whether it describes objects that can be obtained through specific factory methods (and for which there would therefore be no new-style service description), or whether it describes a general service that is available at the global component context, and for which there would thus be a new-style service description.

From the perspective of a user of a UNO object, the object offers one or sometimes even several independent, multiple-inheritance interfaces or old-style services described in the API reference. The services are utilized through method calls grouped in interfaces, and through properties, which are handled through special interfaces as well. Because the access to the functionality is provided by interfaces only, the implementation is irrelevant to a user who wants to use an object.

From the perspective of an implementer of a UNO object, multiple-inheritance interfaces and old-style services are used to define a functionality independently of a programming language and without giving instructions about the internal implementation of the object. Implementing an object means that it must support all specified interfaces and properties. It is possible that a UNO object implements more than one independent, multiple-inheritance interface or old-style service. Sometimes it is useful to implement two or more independent, multiple-inheritance interfaces or services because they have related functionality, or because they support different views to the object.

The RemoteControl service illustration shows the relationship between interfaces and services. The language independent specification of an old-style service with several interfaces is used to implement a UNO object that fulfills the specification. Such a UNO object is sometimes called a "component," although that term is more correctly used to describe deployment entities within a UNO environment. The illustration uses an old-style service description that directly supports multiple interfaces; for a new-style service description, the only difference would be that it would only support one multiple-inheritance interface, which in turn would inherit the other interfaces.

Interfaces, services and implementation

The functionality of a TV system with a TV set and a remote control can be described in terms of service specifications. The interfaces XPower and XChannel described above would be part of a service specification RemoteControl. The new service TVSet consists of the three interfaces XPower, XChannel and XStandby to control the power, the channel selection, the additional power function standby() and a timer() function.

TV System Specification

Referencing Interfaces

References to interfaces in a service definition mean that an implementation of this service must offer the specified interfaces. However, optional interfaces are possible. If a multiple-inheritance interface inherits an optional interface, or an old-style service contains an optional interface, any given UNO object may or may not support this interface. If you utilize an optional interface of a UNO object, always check if the result of queryInterface() is equal to null and react accordingly - otherwise your code will not be compatible with implementations without the optional interface and you might end up with null pointer exceptions. The following UNOIDL snippet shows a fragment of the specification for the old-style com.sun.star.text.TextDocument service in the Apache OpenOffice API. Note the flag optional in square brackets, which makes the interfaces XFootnotesSupplier and XEndnotesSupplier non-mandatory.

  // com.sun.star.text.TextDocument
  service TextDocument
  {
      ...
 
      interface com::sun::star::text::XTextDocument;
      interface com::sun::star::util::XSearchable;
      interface com::sun::star::util::XRefreshable;
      [optional] interface com::sun::star::text::XFootnotesSupplier;
      [optional] interface com::sun::star::text::XEndnotesSupplier;
 
      ...
  };

Service Constructors

New-style services can have constructors, similar to interface methods:

  service SomeService: XSomeInterface { 
      create1();
      create2([in] long arg1, [in] string arg2);
      create3([in] any... rest);
  };

In the above example, there are three explicit constructors, named create1, create2, and create3. The first has no parameters, the second has two normal parameters, and the third has a special rest parameter, which accepts an arbitrary number of any values. Constructor parameters may only be [in], and a rest parameter must be the only parameter of a constructor, and must be of type any; also, unlike an interface method, a service constructor does not specify a return type.

The various language bindings map the UNO constructors into language-specific constructs, which can be used in client code to obtain instances of those services, given a component context. The general convention (followed,for example, by the Java and C++ language bindings) is to map each constructor to a static method (resp. function) with the same name, that takes as a first parameter an XComponentContext, followed by all the parameters specified in the constructor, and returns an (appropriately typed) service instance. If an instance cannot be obtained, a com.sun.star.uno.DeploymentException is thrown. The above SomeService would map to the following Java 1.5 class, for example:

  public class SomeService { 
      public static XSomeInterface create1(
          com.sun.star.uno.XComponentContext context) { ... }
      public static XSomeInterface create2(
          com.sun.star.uno.XComponentContext context, int arg1, String arg2) { ... }
      public static XSomeInterface create3(
          com.sun.star.uno.XComponentContext context, Object... rest) { ... }
  }

Service constructors can also have exception specifications ("raises (Exception1, …)"), which are treated in the same way as exception specifications of interface methods. (If a constructor has no exception specification, it may only throw runtime exceptions, com.sun.star.uno.DeploymentException in particular.)

If a new-style service is written using the short form,

  service SomeService: XSomeInterface;

then it has an implicit constructor. The exact behavior of the implicit constructor is language-binding - specific, but it is typically named create, takes no arguments besides the XComponentContext, and may only throw runtime exceptions.

Including Properties

When the structure of the Apache OpenOffice API was founded, the designers discovered that the objects in an office environment would have huge numbers of qualities that did not appear to be part of the structure of the objects, rather they seemed to be superficial changes to the underlying objects. It was also clear that not all qualities would be present in each object of a certain kind. Therefore, instead of defining a complicated pedigree of optional and non-optional interfaces for each and every quality, the concept of properties was introduced. Properties are data in an object that are provided by name over a generic interface for property access, that contains getPropertyValue() and setPropertyValue() access methods. The concept of properties has other advantages, and there is more to know about properties. Please refer to Properties for further information about properties.

Old-style services can list supported properties directly in the UNOIDL specification. A property defines a member variable with a specific type that is accessible at the implementing component by a specific name. It is possible to add further restrictions to a property through additional flags. The following old-style service references one interface and three optional properties. All known API types can be valid property types:

  // com.sun.star.text.TextContent
  service TextContent
  {
      interface com::sun::star::text::XTextContent;
      [optional, property] com::sun::star::text::TextContentAnchorType AnchorType;
      [optional, readonly, property] sequence<com::sun::star::text::TextContentAnchorType> AnchorTypes;
      [optional, property] com::sun::star::text::WrapTextMode TextWrap;
  };

Possible property flags are:

  • optional
The property does not have to be supported by the implementing component.
  • readonly
The value of the property cannot be changed using com.sun.star.beans.XPropertySet.
  • bound
Changes of property values are broadcast to XPropertyChangeListener, if any were registered through com.sun.star.beans.XPropertySet.
  • constrained
The property broadcasts an event before its value changes. Listeners have the right to veto the change.
  • maybeambiguous
Possibly the property value cannot be determined in some cases, for example, in multiple selections with different values.
  • maybedefault
The value might be stored in a style sheet or in the environment instead of the object itself.
  • maybevoid
In addition to the range of the property type, the value can be void. It is similar to a null value in databases.
  • removable
The property is removable, this is used for dynamic properties.
  • transient
The property will not be stored if the object is serialized

Referencing other Services

Old-style services can include other old-style services. Such references may be optional. That a service is included by another service has nothing to do with implementation inheritance, only the specifications are combined. It is up to the implementer if he inherits or delegates the necessary functionality, or if he implements it from scratch.

The old-style service com.sun.star.text.Paragraph in the following UNOIDL example includes one mandatory service com.sun.star.text.TextContent and five optional services. Every Paragraph must be a TextContent. It can be a TextTable and it is used to support formatting properties for paragraphs and characters:

  // com.sun.star.text.Paragraph
  service Paragraph
  {
      service com::sun::star::text::TextContent;
      [optional] service com::sun::star::text::TextTable;
      [optional] service com::sun::star::style::ParagraphProperties;
      [optional] service com::sun::star::style::CharacterProperties;
      [optional] service com::sun::star::style::CharacterPropertiesAsian;
      [optional] service com::sun::star::style::CharacterPropertiesComplex;
 
      ...
  };

If all the old-style services in the example above were multiple-inheritance interface types instead, the structure would be similar: the multiple-inheritance interface type Paragraph would inherit the mandatory interface TextContent and the optional interfaces TextTable, ParagraphProperties, etc.

Service Implementations in Components

A component is a shared library or Java archive containing implementations of one or more services in one of the target programming languages supported by UNO. Such a component must meet basic requirements, mostly different for the different target language, and it must support the specification of the implemented services. That means all specified interfaces and properties must be implemented. Components must be registered in the UNO runtime system. After the registration all implemented services can be used by ordering an instance of the service at the appropriate service factory and accessing the functionality over interfaces.

Based on our example specifications for a TVSet and a RemoteControl service, a component RemoteTVImpl could simulate a remote TV system:

RemoteTVImpl Component

Such a RemoteTV component could be a jar file or a shared library. It would contain two service implementations, TVSet and RemoteControl. Once the RemoteTV component is registered with the global service manager, users can call the factory method of the service manager and ask for a TVSet or a RemoteControl service. Then they could use their functionality over the interfaces XPower, XChannel and XStandby. When a new implementation of these services with better performance or new features is available later on, the old component can be replaced without breaking existing code, provided that the new features are introduced by adding interfaces.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages