<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2002-2004 The Apache Software Foundation or its licensors,
  as applicable.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">

<document>
  <header>
    <title>Plugin Infrastructure</title>
  </header>

  <body>
    <section id="overview">
      <title>Overview</title>
      <p>Forrest can be extended with the addition of plugins. This document
      describes what a plugin is and outlines the plugin infrastructure so
      that you can start building your own Forrest extensions.</p>
    </section>
      
    <section>
      <title>What is a Forrest Plugin?</title>

      <p>A Forrest plugin is a set of resources and configuration files that 
      extend the functionality of Forrest. They will typically consist of a 
      sitemap, zero or more stylesheets and zero or more schemas.</p>

      <p>The plugins sitemap is mounted by Forrest's sitemap after the project 
      specific sitemap but before the Forrest default matchers. This allows 
      a plugin to override/extend default Forrest behaviour. By adopting a 
      plugin model we can keep the core of Forrest tightly 
      focused on the basic functionality, whilst still facilitating extensions 
      to suit individual projects needs.</p>
      
      <section id="pluginTypes">
        <title>Types of Plugin</title>
        <p>There are three types of plugin, <code>input</code>,
        <code>output</code> and <code>internal</code>. Each plugin has a 
        specific role to play and extends a different part of Forrest:</p>
        
<source>
                            internal plugins
                       (site.xml, abs-linkmap etc.)
                                   |
                                  \|/
                                   .
          input format --> intermediate format --> output format 
                        .                       .
                       /|\                     /|\
                        |                       |
                   input plugin            output plugin
                     (**.xml)         (**.html, **.pdf etc.) 
</source>
        
        <section id="inputPlugins">
          <title>Input Plugins</title>
          <p>Input plugins provide a new source format. For example, the
          OpenOffice.org plugin extends Forrest to allow the use of
          OpenOffice.org Application file formats.</p>
          
          <p>An input plugin provides an <code>input.xmap</code> file. 
          This provides the source matchers (i.e. **.xml), it is 
          mounted in forrest.xmap before the default forrest **.xml behaviour 
          and therefore can override that default behaviour but it will not 
          interfere with any internal Forrest infrastructure matches, or any 
          other plugins infrastructure matches.</p>
          
          <p>An input plugin may also provide a <code>resources.xmap</code>
          file. This can be used to match additional resources that are not 
          stored in XML files, for example, javascript files.</p>
        </section>
        
        <section id="outputPlugins">
          <title>Output Plugins</title>
          
          <p>Output plugins provide a new output format. For example, the
          s5 plugin extends Forrest to produce HTML slides from Forrest
          documents.</p>
          
          <p>An output plugin provides an <code>output.xmap</code> file.
          This provides the relevant output matchers (i.e. 
          **.html, **.pdf, **.slides), it is mounted before any of the default 
          matchers for Forrest and so can override this default behaviour.</p>
        </section>
        
        <section id="internalPlugins">
          <title>Internal Plugins</title>
          
          <p>Internal plugins are for advanced use only. They provide ways 
          of extending or overriding Forrest's
          internal operations. For example, the IMSManifest plugin
          allows Forrest projects to use an IMS Manifest file instead of 
          a site.xml and tabs.xml configuration files.</p>
          
          <p>Internal plugins provide an <code>internal.xmap</code> file. 
          This provides the infrastructure matchers (i.e. 
          site.xml, faq.xml, issues.xml), and will be mounted before 
          *any* of the Forrest matches. This sitemap can override any behaviour 
          within Forrest and so developers of these plugins must be especially
          careful with the construction of their matchers, since they will be
          processed before any other matchers and consequently can easily break
          existing functionality. You must only do a &lt;map:generate ...&gt;
          if you are certain you are going to process the full result. </p>
        </section>
      </section>
      
      <section>
        <title>Naming Conventions</title>
        <p>Technically you can name a plugin anything you like with one
        small restriction (see below). However, we
        do have some naming conventions that we recomend you follow. This is
        to minimise the chances of collision between plugins from different
        developers.</p>
        
        <p>The name should be structured like a java package name, and should
        include a relevant reverse domain name. For example:</p>
        
        <source>org.apache.forrest.plugin.PLUGIN_TYPE.PLUGIN_NAME</source>
        <source>net.sf.forrestPlugins.PLUGIN_TYPE.PLUGIN_NAME</source>
        
        <p>Where <code>PLUGIN_TYPE</code> is either "internal", "input" or
        "output" and <code>PLUGIN_NAME"</code> is a suitable name chosen by
        yourself.</p>
        
        <warning>Plugin names cannot have a '-' character in them. This character
        is used to indicate the start of a version number when defining a plugin
        to be used. See <a href="site:plugins/using">Using Plugins</a> for more 
        information.</warning>
        
      </section>
      
      <section>
        <title>An Example Plugin</title>
  
        <p>In order to fully understand the applicability of Forrest Plugins we 
        will consider an extension to the way in which Forrest defines the 
        structure of the site. By default Forrest uses a site.xml file to 
        define navigation through the site and a tabs.xml file to define the 
        tabs across the top of the page. But what if we want to use a different
        file to describe site structure? For example, what if we want to use an
        IMS Manifest file from the SCORM content package standards 
        (http://www.adlnet.org/).</p>
  
        <p>An IMS Manifest file describes the structure of a site. It is also 
        possible to define a set of rules for extracting tab information from 
        such a file. Consequently, it is possible to use an IMSManifest file to 
        create Forrest's site.xml and tabs.xml files. The advantage would be that
        we can then use SCORM compliant content objects within Forrest.</p>
  
        <p>Unfortunately, IMS Manifests are much more complex than site.xml and 
        tabs.xml files. Therefore, not all users will want to use them. Adding 
        the functionality as an optional plugin seems to be the ideal 
        solution.</p>
      </section>
    </section>

    <section>
      <title>What Does a Forrest Plugin Look Like?</title>

      <p>Plugins will need to conform to a specified directory structure. 
      This mirrors the default forrest directory structure:</p>

<source>
[plugin_name]
  |
  |-- config files (xmap, skinconf etc.)
  |
  |-- resources
      |
      |-- schema
      |   |
      |   |-- catalog.xcat
      |   |
      |   |-- dtd (DTDs etc.)
      |
      |-- stylesheets (XSLs etc.)
</source>
  
    <section>
      <title>The IMS Manifest Plugin</title>

      <p>If we consider the IMS Manifest Plugin described above, we see that we
      will need the following files and directory structure:</p>

     
<source>
org.apache.forrest.plugin.internal.IMSManifest
  |
  |-- sitemap.xmap
  |
  |-- resources
      |
      |-- stylesheets
                    |
                    |- imsmanifest2site.xsl
                    |- imsmanifest2tabs.xsl
                    |- pathutils.xsl
                    |- repositoryUtils.xsl
</source>

      <p>The sitemap.xmap file will override the default behaviour for the 
      navigation generation matchers in Forrest, for example, it contains 
      a matcher as follows:</p>

<source><![CDATA[
<map:match pattern="abs-menulinks">
  <map:select type="exists">
    <map:when test="{project:content.xdocs}imsmanifest.xml">
       <map:generate src="{project:content.xdocs}imsmanifest.xml" />
       <map:transform src="resources/stylesheets/imsmanifest2site.xsl"/>
       <map:transform src="{forrest:stylesheets}/absolutize-linkmap.xsl" />
       <map:transform src="{forrest:stylesheets}/site2site-normalizetabs.xsl" />
     <map:serialize type="xml"/>
   </map:when>
   <map:when test="{project:content.xdocs}site.xml">
      <map:generate src="{project:content.xdocs}site.xml" />
      <map:transform src="{forrest:stylesheets}/absolutize-linkmap.xsl" />
      <map:transform src="{forrest:stylesheets}/site2site-normalizetabs.xsl" />
      <map:transform src="{forrest:stylesheets}/normalizehrefs.xsl"/>
    <map:serialize type="xml"/>
  </map:when>
  </map:select>
</map:match>
]]></source>

      <note>Note that this matcher will default to the behaviour provided by 
      Forrest if there is no imsmanifest.xml file present in the project.
      At present it is necessary to copy this default behaviour from the original
      Forrest *.xmap files. We hope to improve on this in the future.</note>
    </section>
  </section>

  <section>
    <title>How does Installation work?</title>
    <p>When Forrest installs a plugin it downloads a zip of the plugin code and 
    extracts it into the <code>plugins</code> directory of Forrest and an entry is made 
    in <code>src/plugins/sitemap.xmap</code>. For example, installing the 
    IMSManifest plugin described above will result in the following entry 
    being added to the plugin sitemap:</p>

  <source><![CDATA[
<map:select type="exists">
  <map:when test="sitemap.xmap">
    <map:mount uri-prefix="" 
      src="sitemap.xmap" 
      check-reload="yes" 
      pass-through="true"/>
  </map:when>
</map:select>
  ]]></source>
  
      <p>Installed plugins are managed by the
      FORREST_INSTALL_DIR/plugins/sitemap.xmap file. This file is mounted
      by the main Forrest sitemap with the following code:</p>
  
  <source><![CDATA[
        <map:pipeline internal-only="false">
           <map:mount uri-prefix=""
                      src="{forrest:plugins}/sitemap.xmap"
                      check-reload="yes"
                      pass-through="true"/>
        </map:pipeline>
  ]]></source>
      
      <note>The plugin sitemap.xmap file is automatically managed by Forrest, the 
      end user need never edit this file.</note>
    </section>

	<section>
		<title>Further Reading</title>
		<p>If you want to build a plugin you might like to start with our 
		<a href="site:v0.70//howto/buildPlugin">HowTo on Building Plugins</a>.</p>
	</section>
  </body>
</document>
