Changeset 3565
- Timestamp:
- Jul 17, 2007, 1:33:36 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/src/docbook/developerdoc/plugin_developer.xml
r3518 r3565 155 155 <sect2 id="plugin_developer.organize.eclipse"> 156 156 <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> 158 162 </sect2> 159 163 … … 189 193 </itemizedlist> 190 194 191 A plug-in is always required toimplement the195 A plug-in must always implement the 192 196 <interfacename>Plugin</interfacename> interface. 193 197 The <interfacename>InteractivePlugin</interfacename> … … 207 211 <para> 208 212 A plug-in must also have public no-argument contructor. Otherwise, BASE will not 209 be able to create instances of theclass.213 be able to create new instances of the plug-in class. 210 214 </para> 211 215 </important> 212 216 213 217 <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> 216 223 <variablelist> 217 224 <varlistentry> … … 240 247 "Spot images creator", 241 248 "Converts a full-size scanned image into smaller preview jpg " + 242 249 "images for each individual spot.", 243 250 "2.0", 244 251 "2006, Department of Theoretical Physics, Lund University", … … 366 373 <methodsynopsis language="java"> 367 374 <modifier>public</modifier> 375 <type>Collection<Permissions></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> 368 407 <void /> 369 408 <methodname>init</methodname> … … 385 424 <listitem> 386 425 <para> 387 Prepare the plug-in for execution (or configuration). If the plug-in needs426 Prepare the plug-in for execution or configuration. If the plug-in needs 388 427 to do some initialization this is the place to do it. A typical 389 428 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. 391 431 </para> 392 432 <para> … … 407 447 a configuration this object is null. 408 448 The <varname>job</varname> object holds all parameters that are 409 stored together with a <classname>Jo n</classname> object in the449 stored together with a <classname>Job</classname> object in the 410 450 database. This object is null if the plug-in is started without a job. 411 451 </para> … … 426 466 </para> 427 467 <example id="net.sf.basedb.core.plugin.Plugin.init"> 428 <title>The <classname>AbstractPlugin</classname> implementation of thisPlugin.init()</title>468 <title>The <classname>AbstractPlugin</classname> implementation of Plugin.init()</title> 429 469 <programlisting>protected SessionControl sc = null; 430 470 protected ParameterValues configuration = null; … … 469 509 <listitem> 470 510 <para> 471 Runs the plug-in. The <varname>request</varname> 511 Run the plug-in. 512 </para> 513 <para> 514 The <varname>request</varname> 472 515 parameter is of historical interest only. It has no useful information 473 516 and can be ignored. … … 492 535 failed. Not setting a response is considered a failure by the core. From 493 536 the run method it is only allowed to use the 494 <methodname> setDone()</methodname>537 <methodname>Response.setDone()</methodname> 495 538 or the 496 <methodname> setError()</methodname>539 <methodname>Response.setError()</methodname> 497 540 methods. 498 541 </para> 499 542 500 < note>543 <important> 501 544 It is also considered bad practice to let exceptions escape 502 545 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> 504 547 to reporter the error back to the core. 505 </ note>548 </important> 506 549 507 550 <example id="net.sf.basedb.core.plugin.Plugin.run"> … … 581 624 582 625 <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> 584 627 <para> 585 628 If you want the plug-in to be able to interact with the user you must also implement … … 589 632 is one plug-in that does not interact with the user. Instead, the web client has 590 633 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. 593 637 </para> 594 638 <para> … … 1142 1186 The configure method works much like the <methodname>Plugin.run()</methodname> 1143 1187 method. It must return the result in the <classname>Response</classname> object, 1144 and should not t row any exceptions.1188 and should not throw any exceptions. 1145 1189 </para> 1146 1190 … … 1235 1279 1236 1280 <sect2 id="plugin_developer.api.callsequence"> 1237 <title> What happenswhen...</title>1281 <title>How the BASE core interacts with the plug-in when...</title> 1238 1282 1239 1283 <para> … … 1283 1327 If the plug-in implements the <interfacename>InteractivePlugin</interfacename> 1284 1328 interface the <methodname>InteractivePlugin.getGuiContexts()</methodname> 1285 method is called. This is the only time this method . The information it1329 method is called. This is the only time this method is called and the information it 1286 1330 returns are copied and stored in the database. 1287 1331 </para> … … 1362 1406 <listitem> 1363 1407 <para> 1364 The plug-in hasthree different respones:1408 The plug-in can choose between three different respones: 1365 1409 1366 1410 <itemizedlist> … … 1387 1431 <methodname>Response.setContinue()</methodname>: The parameters are correct 1388 1432 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. 1390 1436 </para> 1391 1437 </listitem> … … 1549 1595 Use the <methodname>Response.setDone()</methodname> 1550 1596 method to report success or the <methodname>Response.setError()</methodname> 1551 to report ererrors.1597 to report errors. 1552 1598 </para> 1553 1599 </listitem> … … 1570 1616 <para> 1571 1617 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> 1574 1621 property when constructing the request information object. If this property has 1575 1622 a non-null value, the web client will send the browser to the specified JSP page … … 1679 1726 <sect1 id="plugin_developer.import"> 1680 1727 <title>Import plug-ins</title> 1728 1681 1729 <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. 1686 1733 </para> 1687 1734 1688 1735 <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> 1775 public 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 <!DOCTYPE > 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 1691 1905 </sect2> 1692 1906 1693 1907 <sect2 id="plugin_developer.import.abstractflatfileimporter"> 1694 1908 <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 1960 private PluginParameter<String> nameColumnMapping; 1961 1962 // Parameter that maps the items description from a column 1963 private PluginParameter<String> descriptionColumnMapping; 1964 1965 private RequestInformation getConfigurePluginParameters(GuiContext context) 1966 { 1967 if (configurePlugin == null) 1968 { 1969 // To store parameters for CONFIGURE_PLUGIN 1970 List<PluginParameter<?>> parameters = 1971 new ArrayList<PluginParameter<?>>(); 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<String>( 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<String>( 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 2049 protected 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 2089 private DbControl dc; 2090 private RawDataBatcher batcher; 2091 private RawBioAssay rawBioAssay; 2092 private Map<String, String> columnMappings; 2093 private int numInserted; 2094 2095 @Override 2096 protected 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 2139 protected void handleHeader(Line line) 2140 throws BaseException 2141 { 2142 super.handleHeader(line); 2143 if (line.name() != null && 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> 2192 private Mapper reporterMapper; 2193 private Mapper blockMapper; 2194 private Mapper columnMapper; 2195 private Mapper rowMapper; 2196 // ... more mappers 2197 2198 @Override 2199 protected 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 2242 protected 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 2290 protected 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 2338 protected 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 1696 2353 </sect2> 1697 2354 </sect1> … … 1791 2448 <listitem> 1792 2449 <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. 1794 2452 </para> 1795 2453 </listitem> … … 1850 2508 The plug-in must call <methodname>Response.setDownloadImmediately()</methodname> 1851 2509 instead of <methodname>Response.setDone()</methodname> in <methodname>Plugin.configure()</methodname> 1852 to toend the job configuration wizard. This requests that the core starts2510 to end the job configuration wizard. This requests that the core starts 1853 2511 an immediate download. 1854 2512 </para> … … 1878 2536 <para> 1879 2537 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. 1882 2539 </para> 1883 2540 </listitem> … … 2009 2666 class. It has the same parameters as the <methodname>ImmediateDownloadExporter.doExport()</methodname> 2010 2667 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 the2012 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. 2013 2670 </para> 2014 2671 </listitem> … … 2299 2956 <para> 2300 2957 <exceptionname>UnknownLoginException</exceptionname>: 2301 This exception should be thrown if the login is not know to the2958 This exception should be thrown if the login is not known to the 2302 2959 external authentication system. 2303 2960 </para> … … 2539 3196 The <varname>dir</varname> parameter is the root directory where 2540 3197 the unpacked files should be placed. If the compressed file 2541 contains subdirector ythe plug-in must create those subdirectories3198 contains subdirectories the plug-in must create those subdirectories 2542 3199 unless they already exists. 2543 3200 </para> … … 2567 3224 progress back to the calling code. The plug-in should count 2568 3225 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. 2570 3229 </para> 2571 3230 </listitem>
Note: See TracChangeset
for help on using the changeset viewer.