Tool-writer's interface for the BIRT design model
(also known as the "Design Engine.")
This interface is not meant to be used by customer code
"plugged into" the designer. The customer interface (to be defined)
will be much more abstract and will not provide a way to access the
model objects themselves. This interface is designed as a convenience
for BIRT components that are aware of the model, but need a simple way
to perform common operations.
Package Specification
The BIRT design model (Design Engine) performs a wide
range of low-level tasks:
- Read and write design files.
- Maintain the command history for undo/redo.
- Provide a rich semantic representation of the report design.
- Provide meta-data about the Report Object Model.
- Perform property value validation.
- Notify the application when the model changes.
This API package isolates the GUI and Factory code from the details of the
implemention by providing a series of handle classes. Clients of
this API do not generally work the the actual model
objects. Instead, clients work with API handles that provide higher-level
services. For example, the handles provide "getter" and "setter" methods
for each property of each report element. The model, however, stores
properties as name/value pairs using an abstract representation.
The API encapsulates the complexity of the undo/redo system. While
the "getter" methods are generally just light wrappers on top of the model; but
the "setter" methods invoke the complex machinery needed to make changes
in a way that is undoable and that notifies intersted listeners.
For this reason, the application must
make all changes via this API. Making changes directly to model objects will
put the model into a state inconsistent with the undo/redo stack.
While the tool writer will often use this API, the tool writer is free to
reach down into the lower layers when required for specialized tasks. For
example, the property sheet will likely work directly with meta-data classes
to obtain information about properties such as their type, available choices,
and so on. While the application can query lower-level packages, all updates
must be done though this API as explained above.
Using the API
The application uses the API as follows:
- Start by using the {@link org.eclipse.birt.report.model.api.DesignEngine}
class to create a new design sesion. Specify the user's locale, or use
the default locale. Then, use the design session to create or open
an existing design from a file.
- When the application creates or opens a design, it receives an
{@link org.eclipse.birt.report.model.api.ReportDesignHandle}
instance.
This handle represents the overall report design. The application can have
any number of report designs open concurrently. Use methods on this handle
to save the design to a file, and to access the command stack for undo and
redo.
- Use other methods on the report design handle to navigate to the various
parts of the report. The design provides a number of slots that contain
elements. For example, the Data Source slot contains the design's data
sources, the Body slot contains the sections, and so on.
- Each report element has its own handle type. The application can perform
many generic tasks using the base {@link org.eclipse.birt.report.model.api.DesignElementHandle}
class. Cast
the handle to a specific subclass to work with the operations unique to that
report element.
- The application creates elements using a two-step process. First,
the application uses the {@link org.eclipse.birt.report.model.api.ElementFactory}
class to create the new
element. Then, the application adds the element to the design
by inserting them into a slot of another element.
- A series of properties give the state of each element. Properties
are defined using the
org.eclipse.birt.report.model.metadata
meta-data
package. The application can get and set properties generically using the
property names. Or, the application can use the specific getter/setter
methods on the various specialized handles.
- The application can also work with a variety of property handle classes to
perform specialized tasks, to work with multiple items at one time, and so on.
Higher-Level Operations
In addition to the detailed operations above, many handles provide
additional higher-level operations. For example, operations exist to
add a group to a listing, to change grouping order, and so on.
Note: Most high-level operations are not yet defined in the
current version of the API.
Usage Notes
You should be aware of a number of special features of the API.
Working with Handles
There is a one-to-one correspondence between design elements and handles.
Every design element can have 0 or 1 associated handle. The handle is created
when first needed.
Handles are immuatable: once created, they cannot point to a different element.
Working with Properties
Properties are a core part of the model. The API provides four distinct
ways to work with properties. Choose the one that works best for the
code you are writing.
- Specific getter/setter.
- The various element handles provide
get and set methods for most properties. To avoid cluttering the
interface with accessors for seldom-used properties, the API does not
include accessors for every property. The set of properties exposed
with specific methods will evolve based on the needs of tool writers.
-
- Type-specific getter/setter.
- If no specific getter/setter
exists, or the application wishes to work with properties generically, then
the application can use the type-specific methods such
as
{@link org.eclipse.birt.report.model.api.DesignElementHandle#getIntProperty}
,
{@link org.eclipse.birt.report.model.api.DesignElementHandle#getStringProperty}
,
etc. to get the property. Use
{@link org.eclipse.birt.report.model.api.DesignElementHandle#setIntProperty}
,
{@link org.eclipse.birt.report.model.api.DesignElementHandle#setStringProperty}
,
etc. to set the property. In each
case, you specify the property name. See the element classes in the
org.eclipse.birt.report.model.elements
package for the set of properties
available on each element.
- As generic objects.
-
Properties are stored as objects internally.
Some application code, such as a property sheet, may find it convenient to
work with properties generically. Use the
{@link org.eclipse.birt.report.model.api.DesignElementHandle#getProperty}
and {@link org.eclipse.birt.report.model.api.DesignElementHandle#setProperty}
method to do so.
- Using property iterators and handles.
-
Finally, the API provides
a set of iterators for traversing the set of properties for an element,
and handles for working with each individual property. These classes are
ideal for creating a generic property sheet driven by the set of
properties defined for an element.
Many propeties are simple scalar values. However, quite a few have internal structure.
For example, the highlight property provides a list of highlight rule structures.
Dimension properties provide a CSS-format dimension such as "10in" or "20%".
Specialized handles help parse such properties. Handles also exist for colors,
fonts and others.
Property Inheritance
The vast majority of properties can be inherited. Such properties can
be in one of two states: set or unset. A set property is one for which
a given element has a value. An unset property is one for which an element
does not explicitly have a value; instead the element inherits the value
from its style or the element it extends. If the value is not set in
either of these places, then the property assumes the default value for
that property.
Property inheritance in BIRT is much like that in JavaScript. Both use
prototype-based inheritance. As in JavaScript, BIRT enforces an asymmetry
between getting and setting properties. Most getters will search for the property
up the inheritance hierarchy as explained in the ROM specs. The setter changes
the value only on the target element. Specializd getter methods exist that get
only the local property value without doing a search.
BIRT also provides a set of properties called style properties. These properties
support both JavaScript-like inheritance and CSS-like cascading. See the ROM spec
for details.
The null
value represents an unset property. It is thus important to
understand the difference between, say, and empty string (the property
is set and its value is "") and a null
value (the property is unset.)
Setting a property to a null
value unsets the property for
that element.
Property Types
BIRT supports a number of basic property types: String, Integer,
Float (represented as a double) and Number (represented as a BigDecimal.)
In adddition, BIRT uses a wide range of specialized types such as
dimensions (discussed above), expressions, HTML, XML and so on. In general,
BIRT will automatically convert any property to any of the basic types
if the conversion is meaningful. For example, a choice property can be
obtained as an integer (internal choice code) or string (choice name.)
Some properties are intrinsic -- they are stored as member variables
in the implementation. Many such properties can be set or retrived in two
ways: using the generic property mechanism, or specific get/set methods.
For example, one can get the name using the NAME_PROP property name, or
using the getName( ) method. The primary intrinsic properties are name,
extends and style.
Internal and Display Property Values
When working with the string value of a property, the application must take
care to differentiate between several forms:
- Internal value
- This is the value used within the application and in the XML design file. It is
independent of the user's locale. It is often in a form convenient for scripting
such as "if-empty".
- Localized display value
- This is a string translated to the user's own language. The value is
locale-dependent; it will appear differently in English, Chinese or German. As
a result, it is meaningful only in the current design session; it is translated
into the internal value for persistent storage.
The applicaiton must be sure to call the correct method to get the value as either
a display string or as an internal value. Similarly, distinct methods exist to
set the internal value vs. the display value. In general, call
{@link org.eclipse.birt.report.model.api.DesignElementHandle#getStringProperty}
to get a localized property value
and {@link org.eclipse.birt.report.model.api.DesignElementHandle#setStringProperty} to set a localized property
value. The API will perform any required translation. These calls work for all
properties except lists.
Call {@link org.eclipse.birt.report.model.api.DesignElementHandle#getStringProperty}
to get the internal value of a string property, and
{@link org.eclipse.birt.report.model.api.DesignElementHandle#setStringProperty}
to set the internal value of a string property.
User-Defined Properties
The model supports user-defined properties. These are properties defined
on an element by the user. Once defined, such properties work identically
to system-defined properties. The above property rules, methods and
classes for properties automatically include any user-defined properties.
For example, the property iterator includes user-defined properties.
Dimensions
Dimensions give measurements within the report such
as the size of a page, the (x,y) position of a report item, and so on.
BIRT stores dimension properties using the CSS system: as a numeric measure and
a string unit. The units can be absolute ("in", "cm") or relative ("em", "%").
As a result, the model cannot give the absolute size or position of a report
element. Instead, the application must provide a CSS User Agent (UA)
to compute the layout based on the dimension properties and element content.
For example, a table may choose to be as wide as the page, to have three
columns, and to allocate space in the ratio: 20%, 30% and 50%. Further the
rows of the table may contain text, images, charts and other content. The UA
is responsible for computing the layout based on the dimension properties,
available fonts, actual image sizes and so on.
These calculations are done differently in the Designer UI than in the Presentation
Engine. The Presentation Engine may leverage the end user's browser to do the
layout (by passing the information in HTML), or may implement its own UA. The
Designer UI will emulate a browser UA within the constraints of Eclipse.
The application must have a deep understanding of the CSS specification and
the BIRT Report Object Model (ROM) to correctly interpret dimensions. (This may
seem overly complex, but the alternative -- fixed sizes and positions -- leads
to a report model that is easier to implement, but harder to use.)
Property Handles
Tools that work with properties may wish to use the various property handle
classes.
Property iterators provide access to the set of properties
defined on an element. The property sheet, for example, can use the
iterator to learn about the complete set of properties.
Property handles provide an interface for working with a specific
property.
Properties are defined in one of two ways. System properties are defined
by the Report Object Model and are fixed from one design to the next.
User-defined properties are created by the report developer (as explained
above) and are stored as part of the report design.
System properties can be simple or structured. A simple property is a simple
name/value pair such a name or a dimension. Structured properties represent
a list of objects such as the mapping rules for a style. Property handles
are required to work with structured properties. While the applicaiton
can work directly with the structures to query existing information, the
application must use the property handles to make changes.
Element Containment, Slots and Slot Handles
Many elements act as containers: they can hold other elements
called content. For example,
the report design has slots for data sources, data sets, styles, sections
and more. Container have a slot for their contents. And so on.
The model uses slots to represent the containment relationship.
When you call a method to work with the contents, the API returns a
{@link org.eclipse.birt.report.model.api.SlotHandle}.
Slot handles provide many operations imcluding adding, removing, moving and
enumerating content.
Styles
Styles define the visual characteristics of report items. BIRT defines
a set of standard styles that the report can customize. The report can
add custom styles. Further, each element can override style properites
for that one component.
Therefore, the same set of style properties appear on a wide array of
elements. The application can work with style properties generically
using any handle that represents either a style or an element with
a style. If the application wants to work with specific getter/setter
methods for style properties, it should obtain a
{@link org.eclipse.birt.report.model.api.StyleHandle}
.
There are two ways to obtain a style handle from an element. The first is
to call {@link org.eclipse.birt.report.model.api.DesignElementHandle#getStyle}
.
This method returns a
{@link org.eclipse.birt.report.model.api.SharedStyleHandle}
to the shared style
(if any) that the element references. The other method is
{@link org.eclipse.birt.report.model.api.DesignElementHandle#getPrivateStyle}
, which returns a
{@link org.eclipse.birt.report.model.api.StyleHandle} to work with
the style properties of that specific element. The two style handles
provide the same set of getter and setter methods.
Related Documentation
The application developer should be familiar with the BIRT Report Object
Model. See the following:
- The BIRT design XML schema.
- The BIRT Report Object Model specifications.
- The {@link org.eclipse.birt.report.model.core.DesignElement DesignElement}
class for details on the services that the model offers.
- The {@link org.eclipse.birt.report.model.metadata.MetaDataDictionary
MetaDataDictionary} class for information about element, type, property,
structure and member definitions.