Changeset 3565


Ignore:
Timestamp:
Jul 17, 2007, 1:33:36 PM (14 years ago)
Author:
Nicklas Nordborg
Message:

References #551: Moved doc about import plug-ins from old to new format and updated/added some
information

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/src/docbook/developerdoc/plugin_developer.xml

    r3518 r3565  
    155155    <sect2 id="plugin_developer.organize.eclipse">
    156156      <title>With Eclipse</title>
    157       <para>TODO</para>
     157      <para>
     158        If somebody is willing to add information to this
     159        chapter please send us a note or some written text to put here.
     160        Otherwise, this chapter will be removed.
     161      </para>
    158162    </sect2>
    159163   
     
    189193        </itemizedlist>
    190194       
    191         A plug-in is always required to implement the
     195        A plug-in must always implement the
    192196        <interfacename>Plugin</interfacename> interface.
    193197        The <interfacename>InteractivePlugin</interfacename>
     
    207211        <para>
    208212        A plug-in must also have public no-argument contructor. Otherwise, BASE will not
    209         be able to create instances of the class.
     213        be able to create new instances of the plug-in class.
    210214        </para>
    211215      </important>
    212216     
    213217      <sect3 id="plugin_developer.api.interfaces.plugin">
    214         <title>net.sf.basedb.core.plugin.Plugin</title>
    215         <para>This interface defines seven methods and must be implemented by all plug-ins.</para>
     218        <title>The net.sf.basedb.core.plugin.Plugin interface</title>
     219        <para>
     220          This interface defines the following methods and must be implemented
     221          by all plug-ins.
     222        </para>
    216223        <variablelist>
    217224          <varlistentry>
     
    240247   "Spot images creator",
    241248   "Converts a full-size scanned image into smaller preview jpg " +
    242   "images for each individual spot.",
     249    "images for each individual spot.",
    243250   "2.0",
    244251   "2006, Department of Theoretical Physics, Lund University",
     
    366373              <methodsynopsis language="java">
    367374                <modifier>public</modifier>
     375                <type>Collection&lt;Permissions&gt;</type>
     376                <methodname>getPermissions</methodname>
     377                <void />
     378              </methodsynopsis>
     379            </term>
     380            <listitem>
     381              <para>
     382                Return a collection of permissions that the plug-in needs
     383                to be able to function as expected. This method may return null
     384                or an empty collection. In this case the plug-in permission system
     385                isn't used and the plug-in always get the same permissions as the
     386                logged in user. If permissions are specified the plug-in should
     387                list all permissions it require. Permissions that are not listed
     388                are denied.
     389              </para>
     390              <note>
     391                <para>
     392                The final assignment of permissions to a plug-in is always
     393                at the hands of a server administrator. He/she may decide to
     394                disable the plug-in permission system or revoke some of the
     395                requested permissions. The permissions returned by this method is
     396                only a recommendation that the server administrator may or may not
     397                accept. See <xref linkend="plugins.permissions" />
     398                for more information about plug-in permissions.
     399                </para>
     400              </note>
     401            </listitem>
     402          </varlistentry>
     403          <varlistentry>
     404            <term>
     405              <methodsynopsis language="java">
     406                <modifier>public</modifier>
    368407                <void />
    369408                <methodname>init</methodname>
     
    385424            <listitem>
    386425              <para>
    387                 Prepare the plug-in for execution (or configuration). If the plug-in needs
     426                Prepare the plug-in for execution or configuration. If the plug-in needs
    388427                to do some initialization this is the place to do it. A typical
    389428                implementation however only stores the passed parameters in instance
    390                 variables for later use.
     429                variables for later use. Since it is not possible what the user is going to
     430                do at this stage, we recommend lazy initialisation of all other resources.
    391431              </para>
    392432              <para>
     
    407447                a configuration this object is null.
    408448                The <varname>job</varname> object holds all parameters that are
    409                 stored together with a <classname>Jon</classname> object in the
     449                stored together with a <classname>Job</classname> object in the
    410450                database. This object is null if the plug-in is started without a job.
    411451              </para>
     
    426466              </para>
    427467              <example id="net.sf.basedb.core.plugin.Plugin.init">
    428                 <title>The <classname>AbstractPlugin</classname> implementation of this Plugin.init()</title>
     468                <title>The <classname>AbstractPlugin</classname> implementation of Plugin.init()</title>
    429469<programlisting>protected SessionControl sc = null;
    430470protected ParameterValues configuration = null;
     
    469509            <listitem>
    470510              <para>
    471                 Runs the plug-in. The <varname>request</varname>
     511                Run the plug-in.
     512              </para>
     513              <para>
     514                The <varname>request</varname>
    472515                parameter is of historical interest only. It has no useful information
    473516                and can be ignored.
     
    492535                failed. Not setting a response is considered a failure by the core. From
    493536                the run method it is only allowed to use the
    494                 <methodname>setDone()</methodname>
     537                <methodname>Response.setDone()</methodname>
    495538                or the
    496                 <methodname>setError()</methodname>
     539                <methodname>Response.setError()</methodname>
    497540                methods.
    498541              </para>
    499542             
    500               <note>
     543              <important>
    501544                It is also considered bad practice to let exceptions escape
    502545                out from this method. Always use <code>try...catch</code>
    503                 to catch exceptions and use <code>response.setError()</code>
     546                to catch exceptions and use <code>Response.setError()</code>
    504547                to reporter the error back to the core.
    505               </note>
     548              </important>
    506549             
    507550              <example id="net.sf.basedb.core.plugin.Plugin.run">
     
    581624 
    582625      <sect3 id="plugin_developer.api.interfaces.interactive">
    583         <title>net.sf.basedb.core.plugin.InteractivePlugin</title>
     626        <title>The net.sf.basedb.core.plugin.InteractivePlugin interface</title>
    584627        <para>
    585628          If you want the plug-in to be able to interact with the user you must also implement
     
    589632          is one plug-in that does not interact with the user. Instead, the web client has
    590633          special JSP pages that handles all the interaction, creates a job for it and sets
    591           the parameters. This, kind of hardcoded, approach can be used for other plug-ins as
    592           well, but then it usually requires modification of the client application as well.
     634          the parameters. This, kind of hardcoded, approach can also be used for other
     635          plug-ins, but then it usually requires modification of the client application
     636          as well.
    593637        </para>
    594638        <para>
     
    11421186                The configure method works much like the <methodname>Plugin.run()</methodname>
    11431187                method. It must return the result in the <classname>Response</classname> object,
    1144                 and should not trow any exceptions.
     1188                and should not throw any exceptions.
    11451189              </para>
    11461190             
     
    12351279 
    12361280    <sect2 id="plugin_developer.api.callsequence">
    1237       <title>What happens when...</title>
     1281      <title>How the BASE core interacts with the plug-in when...</title>
    12381282     
    12391283      <para>
     
    12831327          If the plug-in implements the <interfacename>InteractivePlugin</interfacename>
    12841328          interface the <methodname>InteractivePlugin.getGuiContexts()</methodname>
    1285           method is called. This is the only time this method. The information it
     1329          method is called. This is the only time this method is called and the information it
    12861330          returns are copied and stored in the database.
    12871331          </para>
     
    13621406        <listitem>
    13631407          <para>
    1364           The plug-in has three different respones:
     1408          The plug-in can choose between three different respones:
    13651409         
    13661410          <itemizedlist>
     
    13871431            <methodname>Response.setContinue()</methodname>: The parameters are correct
    13881432            but the plug-in wants more parameters. The process continues with
    1389             step <xref linkend="plugin_developer.api.callsequence.configure.requestinformation" />.
     1433            step <xref linkend="plugin_developer.api.callsequence.configure.requestinformation" />
     1434            but the <varname>command</varname> has the value that was passed to the
     1435            <methodname>setContinue()</methodname> method.
    13901436            </para>
    13911437          </listitem>
     
    15491595          Use the <methodname>Response.setDone()</methodname>
    15501596          method to report success or the <methodname>Response.setError()</methodname>
    1551           to reporter errors.
     1597          to report errors.
    15521598          </para>
    15531599        </listitem>
     
    15701616        <para>
    15711617          This is an advanced option for plug-ins that require a different interface for
    1572           specifying plug-in parameters than the default list showing each parameter at a
    1573           time. This feature is used by setting the RequestInformation.getJspPage()
     1618          specifying plug-in parameters than the default list showing one parameter at a
     1619          time. This feature is used by setting the
     1620          <methodname>RequestInformation.getJspPage()</methodname>
    15741621          property when constructing the request information object. If this property has
    15751622          a non-null value, the web client will send the browser to the specified JSP page
     
    16791726  <sect1 id="plugin_developer.import">
    16801727    <title>Import plug-ins</title>
     1728
    16811729    <para>
    1682    
    1683       This documentation is only available in the old format.
    1684       See <ulink url="http://base.thep.lu.se/chrome/site/doc/development/plugins/import/index.html"
    1685         >http://base.thep.lu.se/chrome/site/doc/development/plugins/import/index.html</ulink>
     1730      A plugin becoms an import plugin simply by returning
     1731      <constant>Plugin.MainType.IMPORT</constant>
     1732      from the <methodname>Plugin.getMainType()</methodname> method.
    16861733    </para>
    16871734   
    16881735    <sect2 id="plugin_developer.import.autodetect">
    1689       <title>Autodetecting importer</title>
    1690       <para></para>
     1736      <title>Autodetect file formats</title>
     1737      <para>
     1738        BASE has built-in functionality for autodetecting file formats.
     1739        Your plug-in can be part of that feature if it reads it data
     1740        from a single file. It must also implement the
     1741        <interfacename>AutoDetectingImporter</interfacename>
     1742        interface.
     1743      </para>
     1744
     1745      <sect3 id="plugin_developer.api.interfaces.autodetecting">
     1746        <title>The net.sf.basedb.core.plugin.AutoDetectingImporter interface</title>
     1747
     1748        <variablelist>
     1749        <varlistentry>
     1750          <term>
     1751            <methodsynopsis language="java">
     1752              <modifier>public</modifier>
     1753              <type>boolean</type>
     1754              <methodname>isImportable</methodname>
     1755              <methodparam>
     1756                <type>InputStream</type>
     1757                <parameter>in</parameter>
     1758              </methodparam>
     1759              <exceptionname>BaseException</exceptionname>
     1760            </methodsynopsis>
     1761          </term>
     1762          <listitem>
     1763            <para>
     1764              Check the input stream if it seems to contain data that can be imported by
     1765              the plugin. Usually it means scanning a few lines for some header
     1766              mathing a predefined string or a regexp.
     1767            </para>
     1768            <para>
     1769              The <classname>AbstractFlatFileImporter</classname> implements this method
     1770              by reading the headers from the input stream and checking if
     1771              it stopped at an unknown type of line or not:
     1772              <example>
     1773                <title>Checking file headers</title>
     1774                <programlisting>
     1775public final boolean isImportable(InputStream in)
     1776   throws BaseException
     1777{
     1778   FlatFileParser ffp = getInitializedFlatFileParser();
     1779   ffp.setInputStream(in);
     1780   try
     1781   {
     1782      FlatFileParser.LineType result = ffp.parseHeaders();
     1783      return result != FlatFileParser.LineType.UNKNOWN;
     1784   }
     1785   catch (IOException ex)
     1786   {
     1787      throw new BaseException(ex);
     1788   }
     1789}
     1790</programlisting>
     1791              </example>
     1792            </para>
     1793            <para>
     1794              Note that the input stream doesn't have to be a text file.
     1795              It can be any type of file, for example a binary or an XML file.
     1796              In the case of an XML file you would need to validate the entiry
     1797              input stream in order to be a 100% sure that it is a valid
     1798              xml file, but we recommend that you only check the first few XML tags,
     1799              for example, the &lt;!DOCTYPE &gt; declaration and/or the root element
     1800              tag.
     1801            </para>
     1802          </listitem>
     1803        </varlistentry>
     1804        <varlistentry>
     1805          <term>
     1806            <methodsynopsis language="java">
     1807              <modifier>public</modifier>
     1808              <void/>
     1809              <methodname>doImport</methodname>
     1810              <methodparam>
     1811                <type>InputStream</type>
     1812                <parameter>in</parameter>
     1813              </methodparam>
     1814              <methodparam>
     1815                <type>ProgressReporter</type>
     1816                <parameter>progress</parameter>
     1817              </methodparam>
     1818              <exceptionname>BaseException</exceptionname>
     1819            </methodsynopsis>
     1820          </term>
     1821          <listitem>
     1822            <para>
     1823              Parse the input stream and import all data that is found.
     1824              This method is of course only called if the
     1825              <methodname>isImportable()</methodname> has returned true. Note
     1826              however that the input stream is reopened at the start of the
     1827              file. It may even be the case that the <methodname>isImportable()</methodname>
     1828              method is called on one instance of the plugin and the
     1829              <methodname>doImport()</methodname> method is called on another.
     1830              Thus, the <methodname>doImport()</methodname> can't rely on any state set
     1831              by the <methodname>isImportable()</methodname> method.
     1832            </para>
     1833          </listitem>
     1834        </varlistentry>
     1835        </variablelist>
     1836      </sect3>
     1837     
     1838      <sect3 id="plugin_developer.import.autodetect.callsequence">
     1839        <title>Call sequence during autodetection</title>
     1840       
     1841        <para>
     1842          The call sequence for autodetection resembles the call sequence for
     1843          checking if the plug-in can be used in a given context.
     1844        </para>
     1845
     1846        <orderedlist>
     1847        <listitem>
     1848          <para>
     1849          A new instance of the plug-in class is created. The plug-in must
     1850          have a public no-argument constructor.
     1851          </para>
     1852        </listitem>
     1853       
     1854        <listitem>
     1855          <para>
     1856          The <methodname>Plugin.init()</methodname> method is called.
     1857          The <varname>job</varname> parameter is <constant>null</constant>.
     1858          The <varname>configuration</varname> parameter is <constant>null</constant>
     1859          if the plug-in does not have any configuration parameters.
     1860          </para>
     1861        </listitem>
     1862       
     1863        <listitem>
     1864          <para>
     1865          If the plug-in is interactive the the <methodname>InteractivePlugin.isInContext()</methodname>
     1866          is called. If the context is a list context, the <varname>item</varname>
     1867          parameter is null, otherwise the current item is passed. The plug-in
     1868          should return <constant>null</constant> if it can be used under the
     1869          current circumstances, or a message explaining why not.
     1870          </para>
     1871        </listitem>
     1872       
     1873        <listitem>
     1874          <para>
     1875          If the plug-in can be used the <methodname>AutoDetectingImporter.isImportable()</methodname>
     1876          method is called to check if the selected file is importable or not.
     1877          </para>
     1878        </listitem>
     1879       
     1880        <listitem>
     1881          <para>
     1882          After this, <methodname>Plugin.done()</methodname> is called and
     1883          the plug-in instance is discarded. If there are
     1884          several configurations for a plug-in, this procedure is repeated
     1885          for each configuration. If the plug-in can be used without
     1886          a configuration the procedure is also repeated without
     1887          configuration parameters.
     1888          </para>
     1889        </listitem>
     1890       
     1891        <listitem>
     1892          <para>
     1893          If a single plug-in was found the user is taken to the regular
     1894          job configuration wizard. A new plug-in instance is created for
     1895          this. If more than one plug-in was found the user is presented
     1896          with a list of the plug-ins. After selecting one of them the
     1897          regular job configuration wizard is used with a new plug-in instance.
     1898          </para>
     1899        </listitem>
     1900       
     1901        </orderedlist>
     1902       
     1903      </sect3>
     1904
    16911905    </sect2>
    16921906   
    16931907    <sect2 id="plugin_developer.import.abstractflatfileimporter">
    16941908      <title>The AbstractFlatFileImporter superclass</title>
    1695       <para></para>
     1909      <para>
     1910        The <classname>AbstractFlatFileImporter</classname> is a very useful abstract
     1911        class to use as a superclass for your own import plug-ins. It can be used
     1912        if your plug-in uses regular text files that can be parsed by an instance of the
     1913        <classname>net.sf.basedb.util.FlatFileParser</classname> class. This class parses a file
     1914        by checking each line against a few regular expressions. Depending on which regular
     1915        expression matches the line, it is classified as a header line, a section line,
     1916        a comment, a data line, a footer line or unknown. Header lines are inspected as a group,
     1917        but data lines individually, meaning that it consumes very little memory since only
     1918        a few lines at a time needs to be loaded.
     1919      </para>
     1920     
     1921      <para>
     1922        The <classname>AbstractFlatFileImporter</classname> defines
     1923        <classname>PluginParameter</classname> objects
     1924        for each of the regular expressions and other parameters used by the parser. It also
     1925        implements the <methodname>Plugin.run()</methodname> method and does most of
     1926        the ground work for instantiating a <methodname>FlatFileParser</methodname> and
     1927        parsing the file. What you have to do in your plugin is to put together the
     1928        <classname>RequestInformation</classname> objects
     1929        for configuring the plugin and creating a job and implement the
     1930        <methodname>InteractivePlugin.configure()</methodname> method for validating and
     1931        storing the parameteters. You should also implement or override some methods
     1932        defined by <classname>AbstractFlatFileImporter</classname>.
     1933      </para>
     1934
     1935      <para>
     1936      Here is what you need to do:
     1937      </para>
     1938
     1939      <itemizedlist>
     1940      <listitem>
     1941        <para>
     1942        Implement the <methodname>Plugin.getAbout()</methodname> and
     1943        <methodname>Plugin.getMainType()</methodname> methods. See
     1944        <xref linkend="plugin_developer.api.interfaces.plugin" /> for more information.
     1945        </para>
     1946      </listitem>
     1947     
     1948      <listitem>
     1949        <para>
     1950        Implement the <interfacename>InteractivePlugin</interfacename> methods.
     1951        See <xref linkend="plugin_developer.api.interfaces.interactive" /> for more information. Note that the
     1952        <classname>AbstractFlatFileImporter</classname>
     1953        has defined many parameters for regular expressions used by the parser
     1954        already. You should just pick them and put in your <classname>RequestInformation</classname>
     1955        object.
     1956        </para>
     1957       
     1958        <programlisting>
     1959// Parameter that maps the items name from a column
     1960private PluginParameter&lt;String&gt; nameColumnMapping;
     1961
     1962// Parameter that maps the items description from a column
     1963private PluginParameter&lt;String&gt; descriptionColumnMapping;
     1964
     1965private RequestInformation getConfigurePluginParameters(GuiContext context)
     1966{
     1967   if (configurePlugin == null)
     1968   {
     1969      // To store parameters for CONFIGURE_PLUGIN
     1970      List&lt;PluginParameter&lt;?&gt;&gt; parameters =
     1971         new ArrayList&lt;PluginParameter&lt;?&gt;&gt;();
     1972
     1973      // Parser regular expressions - from AbstractFlatFileParser
     1974      parameters.add(parserSection);
     1975      parameters.add(headerRegexpParameter);
     1976      parameters.add(dataHeaderRegexpParameter);
     1977      parameters.add(dataSplitterRegexpParameter);
     1978      parameters.add(ignoreRegexpParameter);
     1979      parameters.add(dataFooterRegexpParameter);
     1980      parameters.add(minDataColumnsParameter);
     1981      parameters.add(maxDataColumnsParameter);
     1982
     1983      // Column mappings
     1984      nameColumnMapping = new PluginParameter&lt;String&gt;(
     1985         "nameColumnMapping",
     1986         "Name",
     1987         "Mapping that picks the items name from the data columns",
     1988         new StringParameterType(255, null, true)
     1989      );
     1990   
     1991      descriptionColumnMapping = new PluginParameter&lt;String&gt;(
     1992        "descriptionColumnMapping",
     1993        "Description",
     1994        "Mapping that picks the items description from the data columns",
     1995        new StringParameterType(255, null, false)
     1996      );
     1997
     1998      parameters.add(mappingSection);
     1999      parameters.add(nameColumnMapping);
     2000      parameters.add(descriptionColumnMapping);
     2001     
     2002      configurePlugin = new RequestInformation
     2003      (
     2004         Request.COMMAND_CONFIGURE_PLUGIN,
     2005         "File parser settings",
     2006         "",
     2007         parameters
     2008      );
     2009
     2010   }
     2011   return configurePlugin;
     2012}
     2013</programlisting>
     2014      </listitem>
     2015     
     2016      <listitem>
     2017        <para>
     2018        Implement/override some of the methods defined by
     2019        <classname>AbstractFlatFileParser</classname>. The most important
     2020        methods are listed below.
     2021        </para>
     2022      </listitem>
     2023     
     2024      </itemizedlist>
     2025
     2026      <variablelist>
     2027      <varlistentry>
     2028        <term>
     2029          <methodsynopsis language="java">
     2030            <modifier>protected</modifier>
     2031            <type>FlatFileParser</type>
     2032            <methodname>getInitializedFlatFileParser</methodname>
     2033            <exceptionname>BaseException</exceptionname>
     2034          </methodsynopsis>
     2035        </term>
     2036        <listitem>
     2037          <para>
     2038          The method is called to create a <classname>FlatFileParser</classname>
     2039          and set the regular expressions that should be used for parsing the file.
     2040          The default implementation assumes that your plug-in has used the built-in
     2041          <classname>PluginParameter</classname> objects and has stored the values
     2042          at the configuration level. You should override this method if you need to
     2043          initiailise the parser in a different way. See for example the
     2044          code for the <classname>PrintMapFlatFileImporter</classname> plug-in which
     2045          has a fixed format and doesn't use configurations.
     2046          </para>
     2047          <programlisting>
     2048@Override
     2049protected FlatFileParser getInitializedFlatFileParser()
     2050   throws BaseException
     2051{
     2052   FlatFileParser ffp = new FlatFileParser();
     2053   ffp.setSectionRegexp(Pattern.compile("\\[(.+)\\]"));
     2054   ffp.setHeaderRegexp(Pattern.compile("(.+)=,(.*)"));
     2055   ffp.setDataSplitterRegexp(Pattern.compile(","));
     2056   ffp.setDataFooterRegexp(Pattern.compile(""));
     2057   ffp.setMinDataColumns(12);
     2058   return ffp;
     2059}
     2060</programlisting>
     2061        </listitem>
     2062      </varlistentry>
     2063     
     2064      <varlistentry>
     2065        <term>
     2066          <methodsynopsis language="java">
     2067            <modifier>protected</modifier>
     2068            <void/>
     2069            <methodname>begin</methodname>
     2070            <methodparam>
     2071              <type>FlatFileParser</type>
     2072              <parameter>ffp</parameter>
     2073            </methodparam>
     2074            <exceptionname>BaseException</exceptionname>
     2075          </methodsynopsis>
     2076        </term>
     2077        <listitem>
     2078          <para>
     2079          This method is called just before the parsing of the file
     2080          begins. Override this method if you need to initialise some
     2081          internal state. This is, for example, a good place to open
     2082          a <classname>DbControl</classname> object, read parameters from the
     2083          job and configuration and put them into more useful variables. The default
     2084          implementation does nothing, but we recommend that
     2085          <methodname>super.begin()</methodname> is always called.
     2086          </para>
     2087          <programlisting>
     2088// Snippets from the RawDataFlatFileImporter class
     2089private DbControl dc;
     2090private RawDataBatcher batcher;
     2091private RawBioAssay rawBioAssay;
     2092private Map&lt;String, String&gt; columnMappings;
     2093private int numInserted;
     2094
     2095@Override
     2096protected void begin()
     2097   throws BaseException
     2098{
     2099   super.begin();
     2100
     2101   // Get DbControl
     2102   dc = sc.newDbControl();
     2103   rawBioAssay = (RawBioAssay)job.getValue(rawBioAssayParameter.getName());
     2104
     2105   // Reload raw bioassay using current DbControl
     2106   rawBioAssay = RawBioAssay.getById(dc, rawBioAssay.getId());
     2107   
     2108   // Create a batcher for inserting spots
     2109   batcher = rawBioAssay.getRawDataBatcher();
     2110
     2111   // For progress reporting
     2112   numInserted = 0;
     2113}         
     2114</programlisting>
     2115        </listitem>
     2116      </varlistentry>
     2117      <varlistentry>
     2118        <term>
     2119          <methodsynopsis language="java">
     2120            <modifier>protected</modifier>
     2121            <void/>
     2122            <methodname>handleHeader</methodname>
     2123            <methodparam>
     2124              <type>FlatFileParser.Line</type>
     2125              <parameter>line</parameter>
     2126            </methodparam>
     2127            <exceptionname>BaseException</exceptionname>
     2128          </methodsynopsis>
     2129        </term>
     2130        <listitem>
     2131          <para>
     2132          This method is called once for every header line that is found in
     2133          the file. The <varname>line</varname> parameter contains information
     2134          about the header. The default implementation of this method does
     2135          nothing.
     2136          </para>
     2137          <programlisting>
     2138@Override
     2139protected void handleHeader(Line line)
     2140   throws BaseException
     2141{
     2142   super.handleHeader(line);
     2143   if (line.name() != null &amp;&amp; line.value() != null)
     2144   {
     2145      rawBioAssay.setHeader(line.name(), line.value());
     2146   }
     2147}
     2148</programlisting>
     2149        </listitem>
     2150      </varlistentry>
     2151      <varlistentry>
     2152        <term>
     2153          <methodsynopsis language="java">
     2154            <modifier>protected</modifier>
     2155            <void/>
     2156            <methodname>handleSection</methodname>
     2157            <methodparam>
     2158              <type>FlatFileParser.Line</type>
     2159              <parameter>line</parameter>
     2160            </methodparam>
     2161            <exceptionname>BaseException</exceptionname>
     2162          </methodsynopsis>
     2163        </term>
     2164        <listitem>
     2165          <para>
     2166            This method is called once for each section that is found in the file.
     2167            The <varname>line</varname> parameter contains information
     2168            about the section. The default implementation of this method does
     2169            nothing.
     2170          </para>
     2171        </listitem>
     2172      </varlistentry>
     2173     
     2174      <varlistentry>
     2175        <term>
     2176          <methodsynopsis language="java">
     2177            <modifier>protected abstract</modifier>
     2178            <void/>
     2179            <methodname>beginData</methodname>
     2180            <exceptionname>BaseException</exceptionname>
     2181          </methodsynopsis>
     2182        </term>
     2183        <listitem>
     2184          <para>
     2185          This method is called after the headers has been parsed, but before
     2186          the first line of data. This is a good place to add code that
     2187          depends on information in the headers, for example, put
     2188          together column mappings.
     2189          </para>
     2190         
     2191          <programlisting>
     2192private Mapper reporterMapper;
     2193private Mapper blockMapper;
     2194private Mapper columnMapper;
     2195private Mapper rowMapper;
     2196// ... more mappers
     2197
     2198@Override
     2199protected void beginData()
     2200{
     2201   boolean cropStrings = ("crop".equals(job.getValue("stringTooLongError")));
     2202
     2203   // Mapper that always return null; used if no mapping expression has been entered
     2204   Mapper nullMapper = new ConstantMapper((String)null);
     2205   
     2206   // Column mappers
     2207   reporterMapper = getMapper(ffp, (String)configuration.getValue("reporterIdColumnMapping"),
     2208      cropStrings ? ReporterData.MAX_EXTERNAL_ID_LENGTH : null, nullMapper);
     2209   blockMapper = getMapper(ffp, (String)configuration.getValue("blockColumnMapping"), null, nullMapper);
     2210   columnMapper = getMapper(ffp, (String)configuration.getValue("columnColumnMapping"), null, nullMapper);
     2211   rowMapper = getMapper(ffp, (String)configuration.getValue("rowColumnMapping"), null, nullMapper);
     2212   // ... more mappers: metaGrid coordinate, X-Y coordinate, extended properties
     2213   // ...
     2214}
     2215</programlisting>
     2216         
     2217        </listitem>
     2218      </varlistentry>
     2219       
     2220      <varlistentry>
     2221        <term>
     2222          <methodsynopsis language="java">
     2223            <modifier>protected abstract</modifier>
     2224            <void/>
     2225            <methodname>handleData</methodname>
     2226            <methodparam>
     2227              <type>FlatFileParser.Data</type>
     2228              <parameter>data</parameter>
     2229            </methodparam>
     2230            <exceptionname>BaseException</exceptionname>
     2231          </methodsynopsis>
     2232        </term>
     2233        <listitem>
     2234          <para>
     2235          This method is abstract and must be implemented by all subclasses.
     2236          It is called once for every data line in the the file.
     2237          </para>
     2238
     2239          <programlisting>
     2240// Snippets from the RawDataFlatFileImporter class
     2241@Override
     2242protected void handleData(Data data)
     2243   throws BaseException
     2244{
     2245   // Create new RawData object
     2246   RawData raw = batcher.newRawData();
     2247
     2248   // External ID for the reporter
     2249   String externalId = reporterMapper.getValue(data);
     2250   
     2251   // Block, row and column numbers
     2252   raw.setBlock(blockMapper.getInt(data));
     2253   raw.setColumn(columnMapper.getInt(data));
     2254   raw.setRow(rowMapper.getInt(data));
     2255   // ... more: metaGrid coordinate, X-Y coordinate, extended properties
     2256   
     2257   // Insert raw data to the database
     2258   batcher.insert(raw, externalId);
     2259   numInserted++;
     2260}
     2261</programlisting>
     2262         
     2263        </listitem>
     2264      </varlistentry>
     2265     
     2266      <varlistentry>
     2267        <term>
     2268          <methodsynopsis language="java">
     2269            <modifier>protected</modifier>
     2270            <void/>
     2271            <methodname>end</methodname>
     2272            <methodparam>
     2273              <type>boolean</type>
     2274              <parameter>success</parameter>
     2275            </methodparam>
     2276          </methodsynopsis>
     2277        </term>
     2278        <listitem>
     2279          <para>
     2280            Called when the parsing has ended, either because the end of
     2281            file was reached or because an error has occurred. The subclass
     2282            should close any open resources, ie. the <classname>DbControl</classname>
     2283            object. The <varname>success</varname> parameter is <constant>true</constant>
     2284            if the parsing was successful, <constant>false</constant> otherwise.
     2285            The default implementation does nothing.
     2286          </para>
     2287         
     2288          <programlisting>
     2289@Override
     2290protected void end(boolean success)
     2291   throws BaseException
     2292{
     2293   try
     2294   {
     2295      // Commit if the parsing was successful
     2296      if (success)
     2297      {
     2298         batcher.close();
     2299         dc.commit();
     2300      }
     2301   }
     2302   catch (BaseException ex)
     2303   {
     2304      // Well, now we got an exception
     2305      success = false;
     2306      throw ex;
     2307   }
     2308   finally
     2309   {
     2310      // Always close... and call super.end()
     2311      if (dc != null) dc.close();
     2312      super.end(success);
     2313   }
     2314}     
     2315</programlisting>         
     2316        </listitem>
     2317      </varlistentry>
     2318     
     2319      <varlistentry>
     2320        <term>
     2321          <methodsynopsis language="java">
     2322            <modifier>protected</modifier>
     2323            <type>String</type>
     2324            <methodname>getSuccessMessage</methodname>
     2325            <void/>
     2326          </methodsynopsis>
     2327        </term>
     2328        <listitem>
     2329          <para>
     2330          This is the last method that is called, and it is only called if
     2331          everything went suceessfully. This method allows a subclass to generate
     2332          a short message that is sent back to the database as a final progress
     2333          report. The default implementation returns null, which means that no
     2334          message will be generated.
     2335          </para>
     2336          <programlisting>
     2337@Override
     2338protected String getSuccessMessage()
     2339{
     2340   return numInserted + " spots inserted";
     2341}
     2342</programlisting>
     2343        </listitem>
     2344      </varlistentry>
     2345      </variablelist>
     2346
     2347      <para>
     2348        The <classname>AbstractFlatFileImporter</classname> has a lot of
     2349        other methods that you may use and/or override in your own plug-in.
     2350        Check the javadoc for more information.
     2351      </para>
     2352
    16962353    </sect2>
    16972354  </sect1>
     
    17912448        <listitem>
    17922449          <para>
    1793           Set the total size of the exported data (if known).
     2450          Set the total size of the exported data. Don't call this method if the
     2451          total size is not known.
    17942452          </para>
    17952453        </listitem>
     
    18502508        The plug-in must call <methodname>Response.setDownloadImmediately()</methodname>
    18512509        instead of <methodname>Response.setDone()</methodname> in <methodname>Plugin.configure()</methodname>
    1852         to to end the job configuration wizard. This requests that the core starts
     2510        to end the job configuration wizard. This requests that the core starts
    18532511        an immediate download.
    18542512        </para>
     
    18782536        <para>
    18792537        If immediate download is not granted and the job is added to the job queue
    1880         the regular job execution sequence is used. That is, the
    1881         <methodname>Plugin.run()</methodname> method is called.
     2538        the regular job execution sequence is used.
    18822539        </para>
    18832540      </listitem>
     
    20092666        class. It has the same parameters as the <methodname>ImmediateDownloadExporter.doExport()</methodname>
    20102667        method and they have the same meaning. The only difference is that the
    2011         <varname>out</varname> stream can be linked to a file and not just to the
    2012         immediate download.
     2668        <varname>out</varname> stream can be linked to a file in the BASE filesystem
     2669        and not just to the HTTP response stream.
    20132670        </para>
    20142671      </listitem>
     
    22992956              <para>
    23002957              <exceptionname>UnknownLoginException</exceptionname>:
    2301               This exception should be thrown if the login is not know to the
     2958              This exception should be thrown if the login is not known to the
    23022959              external authentication system.
    23032960              </para>
     
    25393196              The <varname>dir</varname> parameter is the root directory where
    25403197              the unpacked files should be placed. If the compressed file
    2541               contains subdirectory the plug-in must create those subdirectories
     3198              contains subdirectories the plug-in must create those subdirectories
    25423199              unless they already exists.
    25433200              </para>
     
    25673224              progress back to the calling code. The plug-in should count
    25683225              the number of bytes read from the <varname>in</varname>
    2569               stream.
     3226              stream. If it is not possible by other means the stream can
     3227              be wrapped by a <classname>net.sf.basedb.util.InputStreamTracker</classname>
     3228              object which has a <methodname>getNumRead()</methodname> method.
    25703229              </para>
    25713230            </listitem>
Note: See TracChangeset for help on using the changeset viewer.