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&lt;String, Object&gt;</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