You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/04/02 10:05:42 UTC
svn commit: r643784 -
/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml
Author: jeremias
Date: Wed Apr 2 01:05:33 2008
New Revision: 643784
URL: http://svn.apache.org/viewvc?rev=643784&view=rev
Log:
More documentation.
Modified:
xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml
Modified: xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml?rev=643784&r1=643783&r2=643784&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml (original)
+++ xmlgraphics/fop/branches/Temp_ProcessingFeedback/src/documentation/content/xdocs/trunk/events.xml Wed Apr 2 01:05:33 2008
@@ -62,8 +62,15 @@
The event subsystem is located in the <code>org.apache.fop.events</code> package and its
base is the <code>Event</code> class. An instance is created for each event and is sent
to a set of <code>EventListener</code> instances by the <code>EventBroadcaster</code>.
- An <code>Event</code> contains an event ID, a source object (which generated the event),
- a severity level (Info, Warning, Error and Fatal Error) and a map of named parameters.
+ An <code>Event</code> contains:
+ </p>
+ <ul>
+ <li>an event ID,</li>
+ <li>a source object (which generated the event),</li>
+ <li>a severity level (Info, Warning, Error and Fatal Error) and</li>
+ <li>a map of named parameters.</li>
+ </ul>
+ <p>
The <code>EventFormatter</code> class can be used to translate the events into
human-readable, localized messages.
</p>
@@ -172,7 +179,244 @@
</section>
<section id="producer">
<title>The producer side (for FOP developers)</title>
- <p>TODO!</p>
+ <p>
+ This section is primarily for FOP and FOP plug-in developers. It describes how to use
+ the event subsystem for producing events.
+ </p>
+ <note>
+ The event package has been designed in order to be theoretically useful for use cases
+ outside FOP. If you think this is interesting independently from FOP, please talk to
+ <a href="mailto:fop-dev@xmlgraphics.apache.org">us</a>.
+ </note>
+ <section id="basic-event-production">
+ <title>Producing and sending an event</title>
+ <p>
+ The basics are very simple. Just instantiate an <code>Event</code> object and fill
+ it with the necessary parameters. Then pass it to the <code>EventBroadcaster</code>
+ which distributes the events to the interested listeneners. Here's a code example:
+ </p>
+ <source><![CDATA[Event ev = new Event(this, "complain", EventSeverity.WARN,
+ Event.paramsBuilder()
+ .param("reason", "I'm tired")
+ .param("blah", new Integer(23))
+ .build());
+EventBroadcaster broadcaster = [get it from somewhere];
+broadcaster.broadcastEvent(ev);
+]]></source>
+ <p>
+ The <code>Event.paramsBuilder()</code> is a
+ <a href="http://en.wikipedia.org/wiki/Fluent_interface">fluent interface</a>
+ to help with the build-up of the parameters. You could just as well instantiate a
+ <code>Map</code> (<code>Map<String, Object></code>) and fill it with values.
+ </p>
+ </section>
+ <section id="event-producer">
+ <title>The EventProducer interface</title>
+ <p>
+ To simplify event production, the event subsystem provides the <code>EventProducer</code>
+ interface. You can create interfaces which extend <code>EventProducer</code>. These
+ interface will contain one method per event to be generated. By contract, each event
+ method must have as its first parameter a parameter named "source" (Type Object) which
+ indicates the object that generated the event. After that come an arbitrary number of
+ parameters of any type as needed by the event.
+ </p>
+ <p>
+ The event producer interface does not need to have any implementation. The implementation
+ is produced at runtime by a dynamic proxy created by <code>DefaultEventBroadcaster</code>.
+ The dynamic proxy creates <code>Event</code> instances for each method call against
+ the event producer interface. Each parameter (except "source") is added to the event's
+ parameter map.
+ </p>
+ <p>
+ To simplify the code needed to get an instance of the event producer interface it is
+ suggested to create an public inner factory class inside the interface.
+ </p>
+ <p>
+ Here's an example of such an event producer interface:
+ </p>
+ <source><![CDATA[public interface MyEventProducer extends EventProducer {
+
+ public class Factory {
+
+ public static MyEventProducer create(EventBroadcaster broadcaster) {
+ return (MyEventProducer)broadcaster.getEventProducerFor(MyEventProducer.class);
+ }
+ }
+
+ /**
+ * Complain about something.
+ * @param source the event source
+ * @param reason the reason for the complaint
+ * @param blah the complaint
+ * @event.severity WARN
+ */
+ void complain(Object source, String reason, int blah);
+
+}]]></source>
+ <p>
+ To produce the same event as in the first example above, you'd user the following code:
+ </p>
+ <source><![CDATA[EventBroadcaster broadcaster = [get it from somewhere];
+TestEventProducer producer = TestEventProducer.Factory.create(broadcaster);
+producer.complain(this, "I'm tired", 23);]]></source>
+ </section>
+ <section id="event-model">
+ <title>The event model</title>
+ <p>
+ Inside an invocation handler for a dynamic proxy, there's no information about
+ the names of each parameter. The JVM doesn't provide it. The only thing you know is
+ the interface and method name. In order to properly fill the <code>Event</code>'s
+ parameter map we need to know the parameter names. These are retrieved from an
+ event object model. This is found in the <code>org.apache.fop.events.model</code>
+ package. The data for the object model is retrieved from an XML representation of the
+ event model that is loaded as a resource. The XML representation is generated using an
+ Ant task at build time (<code>ant resourcegen</code>). The Ant task (found in
+ <code>src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java</code>)
+ scans FOP's sources for descendants of the <code>EventProducer</code> interface and
+ uses <a href="http://qdox.codehaus.org/">QDox</a> to parse these interfaces.
+ </p>
+ <p>
+ Primarily, the QDox-based collector task records the parameters' names and types.
+ Furthermore, it extracts additional attributes embedded as Javadoc comments from
+ the methods. At the moment, the only such attribute is "@event.severity" which indicates
+ the default event severity (which can be changed by event listeners). The example event
+ producer above shows the Javadocs for an event method.
+ </p>
+ <p>
+ There's one more information that is extracted from the event producer information for
+ the event model: an optional primary exception. The first exception in the "throws"
+ declaration of an event method is noted. It is used to throw an exception from
+ the invocation handler if the event has an event severity of "FATAL" when all
+ listeners have been called (listeners can update the event severity). Please note
+ that an implementation of
+ <code>org.apache.fop.events.EventExceptionManager$ExceptionFactory</code> has to be
+ registered for the <code>EventExceptionManager</code> to be able to construct the
+ exception from an event.
+ </p>
+ <p>
+ For a given application, there can be multiple event models active at the same time.
+ In FOP, each renderer is considered to be a plug-in and provides its own specific
+ event model. The individual event models are provided through an
+ <code>EventModelFactory</code>. This interface is implemented for each event model
+ and registered through the service provider mechanism
+ (see the <a href="#plug-ins">plug-ins section</a> for details).
+ </p>
+ </section>
+ <section id="event-severity">
+ <title>Event severity</title>
+ <p>
+ Four different levels of severity for events has been defined:
+ </p>
+ <ol>
+ <li>INFO: informational only</li>
+ <li>WARN: a Warning</li>
+ <li>ERROR: an error condition from which FOP can recover. FOP will continue processing.</li>
+ <li>FATAL: a fatal error which causes an exception in the end and FOP will stop processing.</li>
+ </ol>
+ <p>
+ Event listeners can choose to ignore certain events based on their event severity.
+ Please note that you may receive an event "twice" an a specific case: If there is
+ a fatal error an event is generated and sent to the listeners. After that an exception
+ is thrown with the same information and processing stops. If the fatal event is
+ shown to the user and the following exception is equally presented to the user it
+ may appear that the event is duplicate. Of course, the same information is just
+ published through two different channels.
+ </p>
+ </section>
+ <section id="plug-ins">
+ <title>Plug-ins to the event subsystem</title>
+ <p>
+ The event subsystem is extensible. There are a number of extension points:
+ </p>
+ <ul>
+ <li>
+ <strong><code>org.apache.fop.events.model.EventModelFactory</code>:</strong> Provides
+ an event model to the event subsystem.
+ </li>
+ <li>
+ <strong><code>org.apache.fop.events.EventExceptionManager$ExceptionFactory</code>:</strong>
+ Creates exceptions for events, i.e. turns an event into a specific exception.
+ </li>
+ </ul>
+ <p>
+ The names in bold above are used as filenames for the service provider files that
+ are placed in the <code>META-INF/services</code> directory. That way, they are
+ automatically detected. This is a mechanism defined by the
+ <a href="http://java.sun.com/j2se/1.4.2/docs/guide/jar/jar.html#Service%20Provider">JAR file specification</a>.
+ </p>
+ </section>
+ <section id="l10n">
+ <title>Localization (L10n)</title>
+ <p>
+ One goal of the event subsystem was to have localized (translated) event messages.
+ The <code>EventFormatter</code> class can be used to convert an event to a
+ human-readable message. Each <code>EventProducer</code> can provide its own XML-based
+ translation file. If there is none, a central translation file is used, called
+ "EventFormatter.xml" (found in the same directory as the <code>EventFormatter</code>
+ class).
+ </p>
+ <p>
+ The XML format used by the <code>EventFormatter</code> is the same as
+ <a href="ext:cocoon">Apache Cocoon's</a> catalog format. Here's an example:
+ </p>
+ <source><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<catalogue xml:lang="en">
+ <message key="locator">
+ [ (See position {loc})| (See {#gatherContextInfo})| (No context info available)]
+ </message>
+ <message key="org.apache.fop.render.rtf.RTFEventProducer.explicitTableColumnsRequired">
+ RTF output requires that all table-columns for a table are defined. Output will be incorrect.{{locator}}
+ </message>
+ <message key="org.apache.fop.render.rtf.RTFEventProducer.ignoredDeferredEvent">
+ Ignored deferred event for {node} ({start,if,start,end}).{{locator}}
+ </message>
+</catalogue>
+]]></source>
+ <p>
+ The example (extracted from the RTF handler's event producer) has message templates for
+ two event methods. The class used to do variable replacement in the templates is
+ <code>org.apache.fop.util.text.AdvancedMessageFormat</code> which is more powerful
+ than the <code>MessageFormat</code> classes provided by the Java class library
+ (<code>java.util.text</code> package).
+ </p>
+ <p>
+ "locator" is a template that is reused by the other message templates
+ by referencing it through "{{locator}}". This is some kind of include command.
+ </p>
+ <p>
+ Normal event parameters are accessed by name inside single curly braces, for example:
+ "{node}". For objects, this format just uses the <code>toString()</code> method to turn
+ the object into a string, unless there is an <code>ObjectFormatter</code> registered
+ for that type (there's an example for <code>org.xml.sax.Locator</code>).
+ </p>
+ <p>
+ The single curly braces pattern supports additional features. For example, it is possible
+ to do this: "{start,if,start,end}". "if" here is a special field modifier that evaluates
+ "start" as a boolean and if that is true returns the text right after the second comma
+ ("start"). Otherwise it returns the text after the third comma ("end"). The "equals"
+ modifier is similar to "if" but it takes as an additional (comma-separated) parameter
+ right after the "equals" modifier, a string that is compared to the value of the variable.
+ An example: {severity,equals,EventSeverity:FATAL,,some text} (this adds "some text" if
+ the severity is not FATAL).
+ </p>
+ <p>
+ Additional such modifiers can be added by implementing the
+ <code>AdvancedMessageFormat$Part</code> and <code>AdvancedMessageFormat$PartFactory</code>
+ interfaces.
+ </p>
+ <p>
+ Square braces can be used to specify optional template sections. The whole section will
+ be omitted if any of the variables used within are unavailable. Pipe (|) characters can
+ be used to specify alternative sub-templates (see "locator" above for an example).
+ </p>
+ <p>
+ Developers can also register a function (in the above example:
+ <code>{#gatherContextInfo})</code>
+ to do more complex information rendering. These functions are implementations of the
+ <code>AdvancedMessageFormat$Function</code> interface. Please take care that this is
+ done in a locale-independent way as there is no locale information available, yet.
+ </p>
+ </section>
</section>
</body>
</document>
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org