Changeset 3581


Ignore:
Timestamp:
Jul 20, 2007, 8:23:48 AM (14 years ago)
Author:
Jari Häkkinen
Message:

Merged log:trunk#3533:3580 into the wwebservices branch.

Location:
branches/webservices
Files:
123 edited
8 copied

Legend:

Unmodified
Added
Removed
  • branches/webservices/build.xml

    r3533 r3581  
    144144    name="dist"
    145145    depends="clean,dist.init,core.jar,coreplugins.jar,web.jar,webservices.aar,installprg.jar,
    146       jobagent.jar,migrate.jar,copy.config,copy.jar,doc,doc.dist"
     146      jobagent.jar,migrate.jar,copy.config,copy.jar"
    147147    description="Create everything needed for distribution"
    148148    >
     
    172172  <target
    173173    name="package"
    174     depends="package.bin,package.src"
     174    depends="package.bin"
    175175    description="Generate tar.gz files for the binary and source distribution"
    176176    >
  • branches/webservices/config/dist/extended-properties.xml

    r2959 r3581  
    161161    </property>
    162162  </class>
     163   
     164  <!-- Extended properties for Users -->
     165  <class name="UserData">
     166    <property
     167      name="mobile"
     168      title="Mobile"
     169      description="The user's mobile number"
     170      column="mobile"
     171      type="string"
     172      length="255"
     173    />
     174    <property
     175      name="skype"
     176      title="Skype"
     177      description="The user's skype contact"
     178      column="skype"
     179      type="string"
     180      length="255"
     181    />   
     182  </class>
    163183</extended-properties>
    164184
  • branches/webservices/doc/admin/plugin_configuration/coreplugins.html

    r3133 r3581  
    150150              </tr>
    151151              <tr>
     152                <td>Packed&nbsp;file&nbsp;exporter</td>
     153                <td><i>Not needed</i></td>
     154                <td>BASE 2.4</td>
     155                <td>
     156                  Exports files and directories as an archive-file.
     157              </tr>
     158              <tr class="evenrow">
    152159                <td>Plate&nbsp;mapping&nbsp;exporter</td>
    153160                <td><i>Not needed</i></td>             
     
    155162                <td>Exports plate mappings.</td>
    156163              </tr>
    157               <tr class="evenrow">
     164              <tr>
    158165                <td>Plugin&nbsp;configuration exporter</td>
    159166                <td><i>Not needed</i></td>             
     
    161168                <td>Exports plugin configurations to a XML-file.</td>
    162169              </tr>
    163               <tr>
     170              <tr class="evenrow">
    164171                <td>Table&nbsp;exporter</td>
    165172                <td><i>Not needed</i></td>             
     
    388395              the changes at
    389396              <a
    390               href=http://trac.thep.lu.se/tracs/BASE-hacks>http://trac.thep.lu.se/tracs/BASE-hacks</a>.</td>
     397              href=http://trac.thep.lu.se/trac/BASE-hacks>http://trac.thep.lu.se/trac/BASE-hacks</a>.</td>
    391398          </tr>
    392399        </table>
  • branches/webservices/doc/src/docbook/developerdoc/plugin_developer.xml

    r3533 r3581  
    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                <programlisting>
     1773public final boolean isImportable(InputStream in)
     1774   throws BaseException
     1775{
     1776   FlatFileParser ffp = getInitializedFlatFileParser();
     1777   ffp.setInputStream(in);
     1778   try
     1779   {
     1780      FlatFileParser.LineType result = ffp.parseHeaders();
     1781      return result != FlatFileParser.LineType.UNKNOWN;
     1782   }
     1783   catch (IOException ex)
     1784   {
     1785      throw new BaseException(ex);
     1786   }
     1787}
     1788</programlisting>
     1789            </para>
     1790            <para>
     1791              Note that the input stream doesn't have to be a text file.
     1792              It can be any type of file, for example a binary or an XML file.
     1793              In the case of an XML file you would need to validate the entiry
     1794              input stream in order to be a 100% sure that it is a valid
     1795              xml file, but we recommend that you only check the first few XML tags,
     1796              for example, the &lt;!DOCTYPE &gt; declaration and/or the root element
     1797              tag.
     1798            </para>
     1799          </listitem>
     1800        </varlistentry>
     1801        <varlistentry>
     1802          <term>
     1803            <methodsynopsis language="java">
     1804              <modifier>public</modifier>
     1805              <void/>
     1806              <methodname>doImport</methodname>
     1807              <methodparam>
     1808                <type>InputStream</type>
     1809                <parameter>in</parameter>
     1810              </methodparam>
     1811              <methodparam>
     1812                <type>ProgressReporter</type>
     1813                <parameter>progress</parameter>
     1814              </methodparam>
     1815              <exceptionname>BaseException</exceptionname>
     1816            </methodsynopsis>
     1817          </term>
     1818          <listitem>
     1819            <para>
     1820              Parse the input stream and import all data that is found.
     1821              This method is of course only called if the
     1822              <methodname>isImportable()</methodname> has returned true. Note
     1823              however that the input stream is reopened at the start of the
     1824              file. It may even be the case that the <methodname>isImportable()</methodname>
     1825              method is called on one instance of the plugin and the
     1826              <methodname>doImport()</methodname> method is called on another.
     1827              Thus, the <methodname>doImport()</methodname> can't rely on any state set
     1828              by the <methodname>isImportable()</methodname> method.
     1829            </para>
     1830          </listitem>
     1831        </varlistentry>
     1832        </variablelist>
     1833      </sect3>
     1834     
     1835      <sect3 id="plugin_developer.import.autodetect.callsequence">
     1836        <title>Call sequence during autodetection</title>
     1837       
     1838        <para>
     1839          The call sequence for autodetection resembles the call sequence for
     1840          checking if the plug-in can be used in a given context.
     1841        </para>
     1842
     1843        <orderedlist>
     1844        <listitem>
     1845          <para>
     1846          A new instance of the plug-in class is created. The plug-in must
     1847          have a public no-argument constructor.
     1848          </para>
     1849        </listitem>
     1850       
     1851        <listitem>
     1852          <para>
     1853          The <methodname>Plugin.init()</methodname> method is called.
     1854          The <varname>job</varname> parameter is <constant>null</constant>.
     1855          The <varname>configuration</varname> parameter is <constant>null</constant>
     1856          if the plug-in does not have any configuration parameters.
     1857          </para>
     1858        </listitem>
     1859       
     1860        <listitem>
     1861          <para>
     1862          If the plug-in is interactive the the <methodname>InteractivePlugin.isInContext()</methodname>
     1863          is called. If the context is a list context, the <varname>item</varname>
     1864          parameter is null, otherwise the current item is passed. The plug-in
     1865          should return <constant>null</constant> if it can be used under the
     1866          current circumstances, or a message explaining why not.
     1867          </para>
     1868        </listitem>
     1869       
     1870        <listitem>
     1871          <para>
     1872          If the plug-in can be used the <methodname>AutoDetectingImporter.isImportable()</methodname>
     1873          method is called to check if the selected file is importable or not.
     1874          </para>
     1875        </listitem>
     1876       
     1877        <listitem>
     1878          <para>
     1879          After this, <methodname>Plugin.done()</methodname> is called and
     1880          the plug-in instance is discarded. If there are
     1881          several configurations for a plug-in, this procedure is repeated
     1882          for each configuration. If the plug-in can be used without
     1883          a configuration the procedure is also repeated without
     1884          configuration parameters.
     1885          </para>
     1886        </listitem>
     1887       
     1888        <listitem>
     1889          <para>
     1890          If a single plug-in was found the user is taken to the regular
     1891          job configuration wizard. A new plug-in instance is created for
     1892          this. If more than one plug-in was found the user is presented
     1893          with a list of the plug-ins. After selecting one of them the
     1894          regular job configuration wizard is used with a new plug-in instance.
     1895          </para>
     1896        </listitem>
     1897       
     1898        </orderedlist>
     1899       
     1900      </sect3>
     1901
    16911902    </sect2>
    16921903   
    16931904    <sect2 id="plugin_developer.import.abstractflatfileimporter">
    16941905      <title>The AbstractFlatFileImporter superclass</title>
    1695       <para></para>
     1906      <para>
     1907        The <classname>AbstractFlatFileImporter</classname> is a very useful abstract
     1908        class to use as a superclass for your own import plug-ins. It can be used
     1909        if your plug-in uses regular text files that can be parsed by an instance of the
     1910        <classname>net.sf.basedb.util.FlatFileParser</classname> class. This class parses a file
     1911        by checking each line against a few regular expressions. Depending on which regular
     1912        expression matches the line, it is classified as a header line, a section line,
     1913        a comment, a data line, a footer line or unknown. Header lines are inspected as a group,
     1914        but data lines individually, meaning that it consumes very little memory since only
     1915        a few lines at a time needs to be loaded.
     1916      </para>
     1917     
     1918      <para>
     1919        The <classname>AbstractFlatFileImporter</classname> defines
     1920        <classname>PluginParameter</classname> objects
     1921        for each of the regular expressions and other parameters used by the parser. It also
     1922        implements the <methodname>Plugin.run()</methodname> method and does most of
     1923        the ground work for instantiating a <methodname>FlatFileParser</methodname> and
     1924        parsing the file. What you have to do in your plugin is to put together the
     1925        <classname>RequestInformation</classname> objects
     1926        for configuring the plugin and creating a job and implement the
     1927        <methodname>InteractivePlugin.configure()</methodname> method for validating and
     1928        storing the parameteters. You should also implement or override some methods
     1929        defined by <classname>AbstractFlatFileImporter</classname>.
     1930      </para>
     1931
     1932      <para>
     1933      Here is what you need to do:
     1934      </para>
     1935
     1936      <itemizedlist>
     1937      <listitem>
     1938        <para>
     1939        Implement the <methodname>Plugin.getAbout()</methodname> and
     1940        <methodname>Plugin.getMainType()</methodname> methods. See
     1941        <xref linkend="plugin_developer.api.interfaces.plugin" /> for more information.
     1942        </para>
     1943      </listitem>
     1944     
     1945      <listitem>
     1946        <para>
     1947        Implement the <interfacename>InteractivePlugin</interfacename> methods.
     1948        See <xref linkend="plugin_developer.api.interfaces.interactive" /> for more information. Note that the
     1949        <classname>AbstractFlatFileImporter</classname>
     1950        has defined many parameters for regular expressions used by the parser
     1951        already. You should just pick them and put in your <classname>RequestInformation</classname>
     1952        object.
     1953        </para>
     1954       
     1955        <programlisting>
     1956// Parameter that maps the items name from a column
     1957private PluginParameter&lt;String&gt; nameColumnMapping;
     1958
     1959// Parameter that maps the items description from a column
     1960private PluginParameter&lt;String&gt; descriptionColumnMapping;
     1961
     1962private RequestInformation getConfigurePluginParameters(GuiContext context)
     1963{
     1964   if (configurePlugin == null)
     1965   {
     1966      // To store parameters for CONFIGURE_PLUGIN
     1967      List&lt;PluginParameter&lt;?&gt;&gt; parameters =
     1968         new ArrayList&lt;PluginParameter&lt;?&gt;&gt;();
     1969
     1970      // Parser regular expressions - from AbstractFlatFileParser
     1971      parameters.add(parserSection);
     1972      parameters.add(headerRegexpParameter);
     1973      parameters.add(dataHeaderRegexpParameter);
     1974      parameters.add(dataSplitterRegexpParameter);
     1975      parameters.add(ignoreRegexpParameter);
     1976      parameters.add(dataFooterRegexpParameter);
     1977      parameters.add(minDataColumnsParameter);
     1978      parameters.add(maxDataColumnsParameter);
     1979
     1980      // Column mappings
     1981      nameColumnMapping = new PluginParameter&lt;String&gt;(
     1982         "nameColumnMapping",
     1983         "Name",
     1984         "Mapping that picks the items name from the data columns",
     1985         new StringParameterType(255, null, true)
     1986      );
     1987   
     1988      descriptionColumnMapping = new PluginParameter&lt;String&gt;(
     1989        "descriptionColumnMapping",
     1990        "Description",
     1991        "Mapping that picks the items description from the data columns",
     1992        new StringParameterType(255, null, false)
     1993      );
     1994
     1995      parameters.add(mappingSection);
     1996      parameters.add(nameColumnMapping);
     1997      parameters.add(descriptionColumnMapping);
     1998     
     1999      configurePlugin = new RequestInformation
     2000      (
     2001         Request.COMMAND_CONFIGURE_PLUGIN,
     2002         "File parser settings",
     2003         "",
     2004         parameters
     2005      );
     2006
     2007   }
     2008   return configurePlugin;
     2009}
     2010</programlisting>
     2011      </listitem>
     2012     
     2013      <listitem>
     2014        <para>
     2015        Implement/override some of the methods defined by
     2016        <classname>AbstractFlatFileParser</classname>. The most important
     2017        methods are listed below.
     2018        </para>
     2019      </listitem>
     2020     
     2021      </itemizedlist>
     2022
     2023      <variablelist>
     2024      <varlistentry>
     2025        <term>
     2026          <methodsynopsis language="java">
     2027            <modifier>protected</modifier>
     2028            <type>FlatFileParser</type>
     2029            <methodname>getInitializedFlatFileParser</methodname>
     2030            <exceptionname>BaseException</exceptionname>
     2031          </methodsynopsis>
     2032        </term>
     2033        <listitem>
     2034          <para>
     2035          The method is called to create a <classname>FlatFileParser</classname>
     2036          and set the regular expressions that should be used for parsing the file.
     2037          The default implementation assumes that your plug-in has used the built-in
     2038          <classname>PluginParameter</classname> objects and has stored the values
     2039          at the configuration level. You should override this method if you need to
     2040          initiailise the parser in a different way. See for example the
     2041          code for the <classname>PrintMapFlatFileImporter</classname> plug-in which
     2042          has a fixed format and doesn't use configurations.
     2043          </para>
     2044          <programlisting>
     2045@Override
     2046protected FlatFileParser getInitializedFlatFileParser()
     2047   throws BaseException
     2048{
     2049   FlatFileParser ffp = new FlatFileParser();
     2050   ffp.setSectionRegexp(Pattern.compile("\\[(.+)\\]"));
     2051   ffp.setHeaderRegexp(Pattern.compile("(.+)=,(.*)"));
     2052   ffp.setDataSplitterRegexp(Pattern.compile(","));
     2053   ffp.setDataFooterRegexp(Pattern.compile(""));
     2054   ffp.setMinDataColumns(12);
     2055   return ffp;
     2056}
     2057</programlisting>
     2058        </listitem>
     2059      </varlistentry>
     2060     
     2061      <varlistentry>
     2062        <term>
     2063          <methodsynopsis language="java">
     2064            <modifier>protected</modifier>
     2065            <void/>
     2066            <methodname>begin</methodname>
     2067            <methodparam>
     2068              <type>FlatFileParser</type>
     2069              <parameter>ffp</parameter>
     2070            </methodparam>
     2071            <exceptionname>BaseException</exceptionname>
     2072          </methodsynopsis>
     2073        </term>
     2074        <listitem>
     2075          <para>
     2076          This method is called just before the parsing of the file
     2077          begins. Override this method if you need to initialise some
     2078          internal state. This is, for example, a good place to open
     2079          a <classname>DbControl</classname> object, read parameters from the
     2080          job and configuration and put them into more useful variables. The default
     2081          implementation does nothing, but we recommend that
     2082          <methodname>super.begin()</methodname> is always called.
     2083          </para>
     2084          <programlisting>
     2085// Snippets from the RawDataFlatFileImporter class
     2086private DbControl dc;
     2087private RawDataBatcher batcher;
     2088private RawBioAssay rawBioAssay;
     2089private Map&lt;String, String&gt; columnMappings;
     2090private int numInserted;
     2091
     2092@Override
     2093protected void begin()
     2094   throws BaseException
     2095{
     2096   super.begin();
     2097
     2098   // Get DbControl
     2099   dc = sc.newDbControl();
     2100   rawBioAssay = (RawBioAssay)job.getValue(rawBioAssayParameter.getName());
     2101
     2102   // Reload raw bioassay using current DbControl
     2103   rawBioAssay = RawBioAssay.getById(dc, rawBioAssay.getId());
     2104   
     2105   // Create a batcher for inserting spots
     2106   batcher = rawBioAssay.getRawDataBatcher();
     2107
     2108   // For progress reporting
     2109   numInserted = 0;
     2110}         
     2111</programlisting>
     2112        </listitem>
     2113      </varlistentry>
     2114      <varlistentry>
     2115        <term>
     2116          <methodsynopsis language="java">
     2117            <modifier>protected</modifier>
     2118            <void/>
     2119            <methodname>handleHeader</methodname>
     2120            <methodparam>
     2121              <type>FlatFileParser.Line</type>
     2122              <parameter>line</parameter>
     2123            </methodparam>
     2124            <exceptionname>BaseException</exceptionname>
     2125          </methodsynopsis>
     2126        </term>
     2127        <listitem>
     2128          <para>
     2129          This method is called once for every header line that is found in
     2130          the file. The <varname>line</varname> parameter contains information
     2131          about the header. The default implementation of this method does
     2132          nothing.
     2133          </para>
     2134          <programlisting>
     2135@Override
     2136protected void handleHeader(Line line)
     2137   throws BaseException
     2138{
     2139   super.handleHeader(line);
     2140   if (line.name() != null &amp;&amp; line.value() != null)
     2141   {
     2142      rawBioAssay.setHeader(line.name(), line.value());
     2143   }
     2144}
     2145</programlisting>
     2146        </listitem>
     2147      </varlistentry>
     2148      <varlistentry>
     2149        <term>
     2150          <methodsynopsis language="java">
     2151            <modifier>protected</modifier>
     2152            <void/>
     2153            <methodname>handleSection</methodname>
     2154            <methodparam>
     2155              <type>FlatFileParser.Line</type>
     2156              <parameter>line</parameter>
     2157            </methodparam>
     2158            <exceptionname>BaseException</exceptionname>
     2159          </methodsynopsis>
     2160        </term>
     2161        <listitem>
     2162          <para>
     2163            This method is called once for each section that is found in the file.
     2164            The <varname>line</varname> parameter contains information
     2165            about the section. The default implementation of this method does
     2166            nothing.
     2167          </para>
     2168        </listitem>
     2169      </varlistentry>
     2170     
     2171      <varlistentry>
     2172        <term>
     2173          <methodsynopsis language="java">
     2174            <modifier>protected abstract</modifier>
     2175            <void/>
     2176            <methodname>beginData</methodname>
     2177            <exceptionname>BaseException</exceptionname>
     2178          </methodsynopsis>
     2179        </term>
     2180        <listitem>
     2181          <para>
     2182          This method is called after the headers has been parsed, but before
     2183          the first line of data. This is a good place to add code that
     2184          depends on information in the headers, for example, put
     2185          together column mappings.
     2186          </para>
     2187         
     2188          <programlisting>
     2189private Mapper reporterMapper;
     2190private Mapper blockMapper;
     2191private Mapper columnMapper;
     2192private Mapper rowMapper;
     2193// ... more mappers
     2194
     2195@Override
     2196protected void beginData()
     2197{
     2198   boolean cropStrings = ("crop".equals(job.getValue("stringTooLongError")));
     2199
     2200   // Mapper that always return null; used if no mapping expression has been entered
     2201   Mapper nullMapper = new ConstantMapper((String)null);
     2202   
     2203   // Column mappers
     2204   reporterMapper = getMapper(ffp, (String)configuration.getValue("reporterIdColumnMapping"),
     2205      cropStrings ? ReporterData.MAX_EXTERNAL_ID_LENGTH : null, nullMapper);
     2206   blockMapper = getMapper(ffp, (String)configuration.getValue("blockColumnMapping"), null, nullMapper);
     2207   columnMapper = getMapper(ffp, (String)configuration.getValue("columnColumnMapping"), null, nullMapper);
     2208   rowMapper = getMapper(ffp, (String)configuration.getValue("rowColumnMapping"), null, nullMapper);
     2209   // ... more mappers: metaGrid coordinate, X-Y coordinate, extended properties
     2210   // ...
     2211}
     2212</programlisting>
     2213         
     2214        </listitem>
     2215      </varlistentry>
     2216       
     2217      <varlistentry>
     2218        <term>
     2219          <methodsynopsis language="java">
     2220            <modifier>protected abstract</modifier>
     2221            <void/>
     2222            <methodname>handleData</methodname>
     2223            <methodparam>
     2224              <type>FlatFileParser.Data</type>
     2225              <parameter>data</parameter>
     2226            </methodparam>
     2227            <exceptionname>BaseException</exceptionname>
     2228          </methodsynopsis>
     2229        </term>
     2230        <listitem>
     2231          <para>
     2232          This method is abstract and must be implemented by all subclasses.
     2233          It is called once for every data line in the the file.
     2234          </para>
     2235
     2236          <programlisting>
     2237// Snippets from the RawDataFlatFileImporter class
     2238@Override
     2239protected void handleData(Data data)
     2240   throws BaseException
     2241{
     2242   // Create new RawData object
     2243   RawData raw = batcher.newRawData();
     2244
     2245   // External ID for the reporter
     2246   String externalId = reporterMapper.getValue(data);
     2247   
     2248   // Block, row and column numbers
     2249   raw.setBlock(blockMapper.getInt(data));
     2250   raw.setColumn(columnMapper.getInt(data));
     2251   raw.setRow(rowMapper.getInt(data));
     2252   // ... more: metaGrid coordinate, X-Y coordinate, extended properties
     2253   
     2254   // Insert raw data to the database
     2255   batcher.insert(raw, externalId);
     2256   numInserted++;
     2257}
     2258</programlisting>
     2259         
     2260        </listitem>
     2261      </varlistentry>
     2262     
     2263      <varlistentry>
     2264        <term>
     2265          <methodsynopsis language="java">
     2266            <modifier>protected</modifier>
     2267            <void/>
     2268            <methodname>end</methodname>
     2269            <methodparam>
     2270              <type>boolean</type>
     2271              <parameter>success</parameter>
     2272            </methodparam>
     2273          </methodsynopsis>
     2274        </term>
     2275        <listitem>
     2276          <para>
     2277            Called when the parsing has ended, either because the end of
     2278            file was reached or because an error has occurred. The subclass
     2279            should close any open resources, ie. the <classname>DbControl</classname>
     2280            object. The <varname>success</varname> parameter is <constant>true</constant>
     2281            if the parsing was successful, <constant>false</constant> otherwise.
     2282            The default implementation does nothing.
     2283          </para>
     2284         
     2285          <programlisting>
     2286@Override
     2287protected void end(boolean success)
     2288   throws BaseException
     2289{
     2290   try
     2291   {
     2292      // Commit if the parsing was successful
     2293      if (success)
     2294      {
     2295         batcher.close();
     2296         dc.commit();
     2297      }
     2298   }
     2299   catch (BaseException ex)
     2300   {
     2301      // Well, now we got an exception
     2302      success = false;
     2303      throw ex;
     2304   }
     2305   finally
     2306   {
     2307      // Always close... and call super.end()
     2308      if (dc != null) dc.close();
     2309      super.end(success);
     2310   }
     2311}     
     2312</programlisting>         
     2313        </listitem>
     2314      </varlistentry>
     2315     
     2316      <varlistentry>
     2317        <term>
     2318          <methodsynopsis language="java">
     2319            <modifier>protected</modifier>
     2320            <type>String</type>
     2321            <methodname>getSuccessMessage</methodname>
     2322            <void/>
     2323          </methodsynopsis>
     2324        </term>
     2325        <listitem>
     2326          <para>
     2327          This is the last method that is called, and it is only called if
     2328          everything went suceessfully. This method allows a subclass to generate
     2329          a short message that is sent back to the database as a final progress
     2330          report. The default implementation returns null, which means that no
     2331          message will be generated.
     2332          </para>
     2333          <programlisting>
     2334@Override
     2335protected String getSuccessMessage()
     2336{
     2337   return numInserted + " spots inserted";
     2338}
     2339</programlisting>
     2340        </listitem>
     2341      </varlistentry>
     2342      </variablelist>
     2343
     2344      <para>
     2345        The <classname>AbstractFlatFileImporter</classname> has a lot of
     2346        other methods that you may use and/or override in your own plug-in.
     2347        Check the javadoc for more information.
     2348      </para>
     2349
    16962350    </sect2>
    16972351  </sect1>
     
    17912445        <listitem>
    17922446          <para>
    1793           Set the total size of the exported data (if known).
     2447          Set the total size of the exported data. Don't call this method if the
     2448          total size is not known.
    17942449          </para>
    17952450        </listitem>
     
    18502505        The plug-in must call <methodname>Response.setDownloadImmediately()</methodname>
    18512506        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
     2507        to end the job configuration wizard. This requests that the core starts
    18532508        an immediate download.
    18542509        </para>
     
    18782533        <para>
    18792534        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.
     2535        the regular job execution sequence is used.
    18822536        </para>
    18832537      </listitem>
     
    20092663        class. It has the same parameters as the <methodname>ImmediateDownloadExporter.doExport()</methodname>
    20102664        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.
     2665        <varname>out</varname> stream can be linked to a file in the BASE filesystem
     2666        and not just to the HTTP response stream.
    20132667        </para>
    20142668      </listitem>
     
    20642718      <methodname>Plugin.getMainType()</methodname> method. The information returned from
    20652719      <methodname>InteractivePlugin.getGuiContexts()</methodname>
    2066       must include: [<constant>Item.BIOASSAYSET</constant>, <constant>Type.ITEM</constant>] since
    2067       this is the only place where the web client looks for analysis plug-ins.
     2720      must include: [<constant>Item.BIOASSAYSET</constant>, <constant>Type.ITEM</constant>]
     2721      since this is the main place where the web client looks for analysis plug-ins. If
     2722      the plug-in can work on a subset of the bioassays it may also include
     2723      [<constant>Item.BIOASSAY</constant>, <constant>Type.LIST</constant>]
     2724      among the contexts. This will make it possible for a user to select
     2725      bioassays from the list and then invoke the plug-in.
    20682726    </para>
    20692727   
    2070 <programlisting>private static final Set&lt;GuiContext&gt; guiContexts =
     2728<programlisting>
     2729private static final Set&lt;GuiContext&gt; guiContexts =
    20712730   Collections.singleton(new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM));
    20722731
     
    20762735}</programlisting>
    20772736
     2737    <para>
     2738    If the plugin depends on a specific raw data type or on the number of
     2739    channels, it should check that the current bioassayset is of the
     2740    correct type in the <methodname>InteractivePlugin.isInContext()</methodname>
     2741    method. It is also a good idea to check if the current user has permission
     2742    to use the current experiment. This permission is needed to create new bioassaysets or
     2743    other data belonging to the experiment.
     2744    </para>
     2745 
     2746    <programlisting>
     2747public boolean isInContext(GuiContext context, Object item)
     2748{
     2749   if (item == null)
     2750   {
     2751      message = "The object is null";
     2752   }
     2753   else if (!(item instanceof BioAssaySet))
     2754   {
     2755      message = "The object is not a BioAssaySet: " + item;
     2756   }
     2757   else
     2758   {
     2759      BioAssaySet bas = (BioAssaySet)item;
     2760      int channels = bas.getRawDataType().getChannels();
     2761      if (channels != 2)
     2762      {
     2763         message = "This plug-in requires 2-channel data, not " + channels + "-channel.";
     2764      }
     2765      else
     2766      {
     2767         Experiment e = bas.getExperiment();
     2768         e.checkPermission(Permission.USE);
     2769      }
     2770   }
     2771}
     2772</programlisting>
     2773
     2774    <para>
     2775    The plugin should always include a parameter asking for the current
     2776    bioassay set when the <methodname>InteractivePlugin.getRequestInformation()</methodname>
     2777    is called with <literal>command = Request.COMMAND_CONFIGURE_JOB</literal>.
     2778    </para>
     2779
     2780    <programlisting>
     2781private static final RequestInformation configurePlugin;
     2782private RequestInformation configureJob;
     2783private PluginParameter&lt;BioAssaySet&gt; bioAssaySetParameter;
     2784
     2785public RequestInformation getRequestInformation(GuiContext context, String command)
     2786   throws BaseException
     2787{
     2788   RequestInformation requestInformation = null;
     2789   if (command.equals(Request.COMMAND_CONFIGURE_PLUGIN))
     2790   {
     2791      requestInformation = getConfigurePlugin(context);
     2792   }
     2793   else if (command.equals(Request.COMMAND_CONFIGURE_JOB))
     2794   {
     2795      requestInformation = getConfigureJob(context);
     2796   }
     2797   return requestInformation;
     2798}
     2799
     2800private RequestInformation getConfigureJob(GuiContext context)
     2801{
     2802   if (configureJob == null)
     2803   {
     2804      bioAssaySetParameter; = new PluginParameter&lt;BioAssaySet&gt;(
     2805         "bioAssaySet",
     2806         "Bioassay set",
     2807         "The bioassay set used as the source for this analysis plugin",
     2808         new ItemParameterType&lt;BioAssaySet&gt;(BioAssaySet.class, null, true, 1, null)
     2809      );
     2810
     2811      List&lt;PluginParameter&lt;?&gt;&gt; parameters = new ArrayList&lt;PluginParameter&lt;?&gt;&gt;();
     2812      parameters.add(bioAssaySetParameter);
     2813      // Add more plug-in-specific parameters here...
     2814   
     2815      configureJob = new RequestInformation(
     2816         Request.COMMAND_CONFIGURE_JOB,
     2817         "Configure job",
     2818         "Set parameter for plug-in execution",
     2819         parameters
     2820      );
     2821   }
     2822   return configureJob;
     2823}
     2824</programlisting>
     2825
     2826    <para>
     2827    Of course, the <methodname>InteractivePlugin.configure()</methodname> method needs
     2828    to validate and store the bioassay set parameter as well:
     2829    </para>
     2830 
     2831    <programlisting>
     2832public void configure(GuiContext context, Request request, Response response)
     2833{
     2834   String command = request.getCommand();
     2835   try
     2836   {
     2837      if (command.equals(Request.COMMAND_CONFIGURE_PLUGIN))
     2838      {
     2839         // Validate and store configuration parameters
     2840         response.setDone("Plugin configuration complete");
     2841      }
     2842      else if (command.equals(Request.COMMAND_CONFIGURE_JOB))
     2843      {
     2844         List&lt;Throwable&gt; errors =
     2845            validateRequestParameters(configureJob.getParameters(), request);
     2846         if (errors != null)
     2847         {
     2848            response.setError(errors.size() +
     2849               " invalid parameter(s) were found in the request", errors);
     2850            return;
     2851         }
     2852         storeValue(job, request, bioAssaySetParameter);
     2853         // Store other plugin-specific parameters
     2854     
     2855         response.setDone("Job configuration complete", Job.ExecutionTime.SHORT);
     2856      }
     2857   }
     2858   catch (Throwable ex)
     2859   {
     2860      // Never throw exception, always set response!
     2861      response.setError(ex.getMessage(), Arrays.asList(ex));
     2862   }
     2863}
     2864</programlisting>
     2865
     2866    <para>
     2867    Now, the typical <methodname>Plugin.run()</methodname> method loads the specfied bioassay set
     2868    and it's spot data. It may do some filtering and recalculation of the spot
     2869    intensity value(s). In most cases it will store the result as a child bioassay
     2870    set with one bioassay for each bioassay in the parent bioassay set.
     2871    Here is an example, which just copies the intensity values, while
     2872    removing those with a negative value in either channel.
     2873    </para>
     2874 
     2875    <programlisting>
     2876public void run(Request request, Response response, ProgressReporter progress)
     2877{
     2878   DbControl dc = sc.newDbControl();
     2879   try
     2880   {
     2881      BioAssaySet source = (BioAssaySet)job.getParameter("bioAssaySet");
     2882      // Reload with current DbControl
     2883      source = BioAssaySet.getById(dc, source.getId());
     2884      int channels = source.getRawDataType().getChannels();
     2885     
     2886      // Create transformation and new bioassay set
     2887      Job j = Job.getById(dc, job.getId());
     2888      Transformation t = source.newTransformation(j);
     2889      t.setName("Copy spot intensities &gt;= 0");
     2890      dc.saveItem(t);
     2891
     2892      BioAssaySet result = t.newProduct(null, "new", true);
     2893      result.setName("After: Copying spot intensities");
     2894      dc.saveItem(result);
     2895
     2896      // Get query for source data
     2897      DynamicSpotQuery query = source.getSpotData();
     2898     
     2899      // Do not return spots with intensities &lt; 0
     2900      for (int ch = 1; ch &lt;= channels; ++ch)
     2901      {
     2902         query.restrict(
     2903            Restrictions.gteq(
     2904               Dynamic.column(VirtualColumn.channel(ch)),
     2905               Expressions.integer(0)
     2906            )
     2907         );
     2908      }
     2909     
     2910      // Create batcher and copy data
     2911      SpotBatcher batcher = result.getSpotBatcher();
     2912      int spotsCopied = batcher.insert(query);
     2913      batcher.close();
     2914     
     2915      // Commit and return
     2916      dc.commit();
     2917      response.setDone("Copied " + spotsCopied + " spots.");
     2918   }
     2919   catch (Throwable t)
     2920   {
     2921      response.setError(t.getMessage(), Arrays.asList(t));
     2922   }
     2923   finally
     2924   {
     2925      if (dc != null) dc.close();
     2926   }
     2927}
     2928</programlisting>
     2929
     2930    <para>
     2931    See <xref linkend="api_overview.dynamic_and_batch_api" />
     2932    for more examples of using the analysis API.
     2933    </para>
     2934
     2935    <sect2 id="plugin_developer.analyse.abstractanalysis">
     2936      <title>The AbstractAnalysisPlugin class</title>
     2937     
    20782938      <para>
    2079         More documentation is available in the old format.
    2080         See <ulink url="http://base.thep.lu.se/chrome/site/doc/development/plugins/analysis/index.html"
    2081           >http://base.thep.lu.se/chrome/site/doc/development/plugins/analysis/index.html</ulink>
     2939        This class is an abstract base class. It is a useful
     2940        class for most analysis plug-ins to inherit from. It's main
     2941        purpose is to define <classname>PluginParameter</classname>
     2942        objects that are commonly used in analysis plug-ins. This includes:
    20822943      </para>
    2083 
     2944     
     2945      <itemizedlist>
     2946      <listitem>
     2947        <para>
     2948        The source bioassay set:
     2949          <methodname>getSourceBioAssaySetParameter()</methodname>,
     2950          <methodname>getCurrentBioAssaySet()</methodname>,
     2951          <methodname>getSourceBioAssaySet()</methodname>
     2952        </para>
     2953      </listitem>
     2954      <listitem>
     2955        <para>
     2956        The name and description of the child bioassay set that
     2957        is going to be created by the plug-in:
     2958        <methodname>getChildNameParameter()</methodname>,
     2959        <methodname>getChildDescriptionParameter()</methodname>
     2960        </para>
     2961      </listitem>
     2962      <listitem>
     2963        <para>
     2964        The name and description of the transformation that
     2965        represents the execution of the plug-in:
     2966        <methodname>getTransformationNameParameter()</methodname>,
     2967        <methodname>getTransformationName()</methodname>
     2968        </para>
     2969      </listitem>
     2970      </itemizedlist>
     2971     
     2972    </sect2>
    20842973
    20852974  </sect1>
     
    22993188              <para>
    23003189              <exceptionname>UnknownLoginException</exceptionname>:
    2301               This exception should be thrown if the login is not know to the
     3190              This exception should be thrown if the login is not known to the
    23023191              external authentication system.
    23033192              </para>
     
    25393428              The <varname>dir</varname> parameter is the root directory where
    25403429              the unpacked files should be placed. If the compressed file
    2541               contains subdirectory the plug-in must create those subdirectories
     3430              contains subdirectories the plug-in must create those subdirectories
    25423431              unless they already exists.
    25433432              </para>
     
    25673456              progress back to the calling code. The plug-in should count
    25683457              the number of bytes read from the <varname>in</varname>
    2569               stream.
     3458              stream. If it is not possible by other means the stream can
     3459              be wrapped by a <classname>net.sf.basedb.util.InputStreamTracker</classname>
     3460              object which has a <methodname>getNumRead()</methodname> method.
    25703461              </para>
    25713462            </listitem>
  • branches/webservices/doc/src/docbook/overviewdoc/resources.xml

    r3533 r3581  
    117117        or requesting a new feature. Perhaps someone has registered the issue as a ticket
    118118        already. This list can also be used to see how the BASE 2 development is proceeding
    119         and when some particular request is planed to be fixed.
     119        and when some particular request is planned to be fixed.
    120120      </para>
    121121
  • branches/webservices/doc/src/docbook/userdoc/file_system.xml

    r3533 r3581  
    331331                  These settings are only active if you select
    332332                  a compressed file format that BASE knows how to
    333                   unpack. Currently, BASE ships with support for zip-files,
     333                  unpack. BASE ships with support for some of the most common
     334                  compressed file formats, such as zip and tar,
    334335                  but this can be extended by the use of plug-ins.
    335336                  <nohelp>See <xref linkend="plugin_developer.other.unpacker"
  • branches/webservices/doc/src/docbook/userdoc/webclient.xml

    r3533 r3581  
    460460        </helptext>
    461461       
     462      </sect2>
     463     
     464      <sect2 id="webclient.configuration.other">
     465        <title>Other information</title>
     466        <para>
     467          Use the
     468          <menuchoice>
     469            <guimenu>File</guimenu>
     470            <guimenuitem>Other information&hellip;</guimenuitem>
     471          </menuchoice>
     472          menu to bring up the other information dialog.
     473        </para>
     474        <helptext external_id="userpreferences.other" title="Other information">
     475          <para>
     476            This dialog has three tabs,
     477            <guilabel>Contact information</guilabel>
     478            ,
     479            <guilabel>Password</guilabel>
     480            and
     481            <guilabel>Other information</guilabel>
     482            (selected) .
     483          </para>
     484          <para>
     485            The look of the
     486            <guilabel>Other information</guilabel>
     487            tab can differe abit between different servers, depending on what settings
     488            the server is installed with. There are three inputs in a fresh BASE2
     489            installation but it is only the
     490            <guilabel>Description</guilabel>
     491            textarea that is static, the others can be removed or more fields can be
     492            added (managed by the server administrator). The three fields, included in a
     493            the BASE2 installation, are
     494            <variablelist>
     495              <varlistentry>
     496                <term>
     497                  <guilabel>Mobile</guilabel>
     498                </term>
     499                <listitem>
     500                  <para>Your mobile number(Optional).</para>
     501                </listitem>
     502              </varlistentry>
     503              <varlistentry>
     504                <term>
     505                  <guilabel>Skype</guilabel>
     506                </term>
     507                <listitem>
     508                  <para>Your skype contact information(Optional).</para>
     509                </listitem>
     510              </varlistentry>
     511              <varlistentry>
     512                <term>
     513                  <guilabel>Description</guilabel>
     514                </term>
     515                <listitem>
     516                  <para>
     517                    Text area where you can put useful information that couldn't
     518                    be stored anywhere else(Optional).
     519                  </para>
     520                </listitem>
     521              </varlistentry>
     522            </variablelist>
     523          </para>
     524          <para>Press &gbSave; to save the changes or &gbCancel; to abort.</para>
     525          <seeother>
     526            <other external_id="userpreferences.contact">Contact information</other>
     527            <other external_id="userpreferences.password">Change password</other>
     528          </seeother>
     529        </helptext>
    462530      </sect2>
    463531
  • branches/webservices/src/clients/web/net/sf/basedb/clients/web/DynamicUtil.java

    r2993 r3581  
    7070    Formatter<Number> intFormatter = FormatterFactory.getIntFormatter(sc);
    7171    columns.add(new TableColumn("POSITION", "POSITION", null, Type.INT,
    72       "Position", "Spot position", "always", true, true, true, false, intFormatter));
     72      "Position", "Spot position", "always", true, true, true,
     73      Formula.AverageMethod.NONE, intFormatter));
    7374    for (int channel = 1; channel <= channels; ++channel)
    7475    {
    7576      TableColumn tc = new TableColumn("ch"+channel, "%"+channel, "ch("+channel+")",
    76         Type.FLOAT, "Ch "+channel, "Channel " + channel + " intensity");
    77       tc.setFormatter(numberFormatter);
     77        Type.FLOAT, "Ch "+channel, "Channel " + channel + " intensity", "auto", true, true, true,
     78        Formula.AverageMethod.ARITHMETIC_MEAN, numberFormatter);
    7879      columns.add(tc);
    7980    }
     
    8788      Formatter<Number> intFormatter = FormatterFactory.getIntFormatter(sc);
    8889      columns.add(new TableColumn(idPrefix + "position", propertyPrefix+"position", "raw('position')",
    89         Type.INT, titlePrefix+"Position", "Raw spot position", "auto", true, true, true, false, intFormatter));
     90        Type.INT, titlePrefix+"Position", "Raw spot position", "auto", true, true, true,
     91        Formula.AverageMethod.NONE, intFormatter));
    9092      columns.add(new TableColumn(idPrefix + "block", propertyPrefix+"block", "raw('block')",
    91         Type.INT, titlePrefix+"Block", "Block number", "auto", true, true, true, false, intFormatter));
     93        Type.INT, titlePrefix+"Block", "Block number", "auto", true, true, true,
     94        Formula.AverageMethod.NONE, intFormatter));
    9295      columns.add(new TableColumn(idPrefix + "metaGridX", propertyPrefix+"metaGridX", "raw('metaGridX')",
    93         Type.INT, titlePrefix+"Meta grid X", "Meta X coordinate", "auto", true, true, true, false, intFormatter));
     96        Type.INT, titlePrefix+"Meta grid X", "Meta X coordinate", "auto", true, true, true,
     97        Formula.AverageMethod.NONE, intFormatter));
    9498      columns.add(new TableColumn(idPrefix + "metaGridY", propertyPrefix+"metaGridY", "raw('metaGridY')",
    95         Type.INT, titlePrefix+"Meta grid Y", "Meta Y coordinate", "auto", true, true, true, false, intFormatter));
     99        Type.INT, titlePrefix+"Meta grid Y", "Meta Y coordinate", "auto", true, true, true,
     100        Formula.AverageMethod.NONE, intFormatter));
    96101      columns.add(new TableColumn(idPrefix + "row", propertyPrefix+"row", "raw('row')", Type.INT,
    97         titlePrefix+"Row", "Row number", "auto", true, true, true, false, intFormatter));
     102        titlePrefix+"Row", "Row number", "auto", true, true, true,
     103        Formula.AverageMethod.NONE, intFormatter));
    98104      columns.add(new TableColumn(idPrefix + "column", propertyPrefix+"column", "raw('column')",
    99         Type.INT, titlePrefix+"Column", "Column number", "auto", true, true, true, false, intFormatter));
     105        Type.INT, titlePrefix+"Column", "Column number", "auto", true, true, true,
     106        Formula.AverageMethod.NONE, intFormatter));
    100107      columns.add(new TableColumn(idPrefix + "x", propertyPrefix+"x", "raw('x')", Type.INT,
    101         titlePrefix+"X", "X coordinate", "auto", true, true, true, false, intFormatter));
     108        titlePrefix+"X", "X coordinate", "auto", true, true, true,
     109        Formula.AverageMethod.NONE, intFormatter));
    102110      columns.add(new TableColumn(idPrefix + "y", propertyPrefix+"y", "raw('y')", Type.INT,
    103         titlePrefix+"Y", "Y coordinate", "auto", true, true, true, false, intFormatter));
     111        titlePrefix+"Y", "Y coordinate", "auto", true, true, true,
     112        Formula.AverageMethod.NONE, intFormatter));
    104113 
    105114      List<RawDataProperty> rdpList = rawDataType.getProperties();
     
    109118        TableColumn tc = new TableColumn(idPrefix+rdpName, propertyPrefix+rdpName, "raw('"+rdpName+"')", rdp.getType(),
    110119          titlePrefix + rdp.getTitle(), rdp.getDescription(), "auto", true, true, true,
    111           rdp.isAveragable(), FormatterFactory.getExtendedPropertyFormatter(sc, rdp));
     120          rdp.getAverageMethod(), FormatterFactory.getExtendedPropertyFormatter(sc, rdp));
    112121        columns.add(tc);
    113122      }
     
    121130    Formatter<Date> dateFormatter = FormatterFactory.getDateFormatter(sc);
    122131    columns.add(new TableColumn(idPrefix + "name", propertyPrefix+"name", "rep('name')",
    123       Type.STRING, titlePrefix + "Name", "Reporter name", "auto", true, true, true, false, stringFormatter));
     132      Type.STRING, titlePrefix + "Name", "Reporter name", "auto", true, true, true,
     133      Formula.AverageMethod.NONE, stringFormatter));
    124134    columns.add(new TableColumn(idPrefix + "externalId", propertyPrefix+"externalId", "rep('externalId')",
    125       Type.STRING, titlePrefix + "ID", "Reporter ID", "auto", true, true, true, false, stringFormatter));
     135      Type.STRING, titlePrefix + "ID", "Reporter ID", "auto", true, true, true,
     136      Formula.AverageMethod.NONE, stringFormatter));
    126137    columns.add(new TableColumn(idPrefix + "symbol", propertyPrefix+"symbol", "rep('symbol')",
    127       Type.STRING, titlePrefix + "Gene symbol", "Gene symbol", "auto", true, true, true, false, stringFormatter));
     138      Type.STRING, titlePrefix + "Gene symbol", "Gene symbol", "auto", true, true, true,
     139      Formula.AverageMethod.NONE, stringFormatter));
    128140    columns.add(new TableColumn(idPrefix + "description", propertyPrefix+"description", "rep('description')",
    129       Type.STRING, titlePrefix + "Description", "Reporter description", "auto", true, true, true, false, stringFormatter));
     141      Type.STRING, titlePrefix + "Description", "Reporter description", "auto", true, true, true,
     142      Formula.AverageMethod.NONE, stringFormatter));
    130143    columns.add(new TableColumn(idPrefix + "lastUpdate", propertyPrefix+"lastUpdate", "rep('lastUpdate')",
    131       Type.DATE, titlePrefix + "Last update", "Last updateded", "auto", true, true, true, false, dateFormatter));
     144      Type.DATE, titlePrefix + "Last update", "Last updateded", "auto", true, true, true,
     145      Formula.AverageMethod.NONE, dateFormatter));
    132146
    133147    List<ExtendedProperty> extended = ExtendedProperties.getProperties("ReporterData");
     
    138152        String name = ep.getName();
    139153        TableColumn tc = new TableColumn(idPrefix + name, propertyPrefix + name, "rep('"+name+"')",
    140           ep.getType(), titlePrefix + ep.getTitle(), ep.getDescription());
    141         tc.setFormatter(FormatterFactory.getExtendedPropertyFormatter(sc, ep));
     154          ep.getType(), titlePrefix + ep.getTitle(), ep.getDescription(), "auto", true, true, true,
     155          ep.getAverageMethod(), FormatterFactory.getExtendedPropertyFormatter(sc, ep));
    142156        columns.add(tc);
    143157      }
     
    155169    {
    156170      ExtraValue ev = result.next();
    157       ExtraValueType evt = ev.getExtraValueType();
    158171      int id = ev.getId();
    159       TableColumn tc = new TableColumn(idPrefix+id, propertyPrefix + id, "xtra('" + evt.getExternalId() + "')", ev.getValueType(),
    160         titlePrefix+evt.getName(), evt.getDescription());
    161       Formatter<?> formatter = FormatterFactory.getTypeFormatter(sc, evt.getValueType());
    162       if (evt.getValueType().isNumerical())
    163       {
    164         // Numerical types *should* return a numberic formatter which is required by the color formatter
     172      ExtraValueType evt = null;
     173      TableColumn tc = null;
     174      try
     175      {
     176        evt = ev.getExtraValueType();
     177        tc = new TableColumn(idPrefix+id, propertyPrefix + id, "xtra('" + evt.getExternalId() + "')",
     178            ev.getValueType(), titlePrefix+evt.getName(), evt.getDescription(),
     179            "auto", true, true, true, evt.getAverageMethod(), null);
     180      }
     181      catch (Throwable t)
     182      {
     183        tc = new TableColumn(idPrefix+id, propertyPrefix + id, "xtra('" + id + "')",
     184            ev.getValueType(), titlePrefix+ev.getValueType(), "",
     185            "auto", true, true, true, null, null);
     186      }
     187      Formatter<?> formatter = FormatterFactory.getTypeFormatter(sc, ev.getValueType());
     188      if (ev.getValueType().isNumerical() && evt != null)
     189      {
     190        // Numerical types *should* return a numeric formatter which is required by the color formatter
    165191        formatter = FormatterFactory.getColorFormatter(sc, evt.getColoring(),
    166192          (Formatter<Number>)formatter);
     
    188214      {
    189215        TableColumn tc = new TableColumn(idPrefix+f.getId(), "="+jepExpression, jepExpression, Type.FLOAT,
    190             titlePrefix + f.getName(), f.getDescription());
     216            titlePrefix + f.getName(), f.getDescription(), "auto", true, true, true,
     217            f.getAverageMethod(), null);
    191218        tc.setFormatter(FormatterFactory.getColorFormatter(sc, f.getColoring(), numberFormatter));
    192219        columns.add(tc);
     
    200227    List<String> selectedIds = new ArrayList<String>(columns.size());
    201228    List<String> selectedProperties = new ArrayList<String>(columns.size());
     229    List<TableColumn> selectedColumns = new ArrayList<TableColumn>(columns.size());
    202230   
    203231    String visibleColumns = cc.getSetting("columns");
     
    213241          selectedProperties.add(tc.getProperty());
    214242          selectedIds.add(tc.getId());
     243          selectedColumns.add(tc);
    215244        }
    216245      }
    217246    }
    218     return new SelectedInfo(selectedProperties, selectedIds);
     247    return new SelectedInfo(selectedProperties, selectedIds, selectedColumns);
    219248  }
    220249 
     
    223252    public final List<String> selectedProperties;
    224253    public final List<String> selectedIds;
     254    public final List<TableColumn> selectedColumns;
    225255   
    226     private SelectedInfo(List<String> properties, List<String> ids)
     256    private SelectedInfo(List<String> properties, List<String> ids, List<TableColumn> columns)
    227257    {
    228258      this.selectedIds = ids;
    229259      this.selectedProperties = properties;
     260      this.selectedColumns = columns;
    230261    }
    231262  }
  • branches/webservices/src/clients/web/net/sf/basedb/clients/web/ExperimentExplorer.java

    r3533 r3581  
    3636import net.sf.basedb.util.Values;
    3737import net.sf.basedb.clients.web.formatter.FormatterFactory;
     38import net.sf.basedb.clients.web.taglib.table.TableColumn;
    3839import net.sf.basedb.core.AnnotationType;
    3940import net.sf.basedb.core.BaseException;
     
    712713    @return A query
    713714  */
    714   public DynamicSpotQuery getSpotQuery(DbControl dc, ReporterData reporter, int positionIndex, List<String> selectionList)
     715  public DynamicSpotQuery getSpotQuery(DbControl dc, ReporterData reporter, int positionIndex, List<TableColumn> selectionList)
    715716  {
    716717    BioAssaySet bioAssaySet = getBioAssaySet(dc);
     
    780781    // Set additional selected columns
    781782    int i = 0;
    782     for (String selectProperty : selectionList)
     783    for (TableColumn tc : selectionList)
    783784    {
    784785      // Skip channel intensities since they are already selected
    785       if (!selectProperty.startsWith("%"))
     786      if (!tc.getProperty().startsWith("%"))
    786787      {
    787         Expression select = ItemContext.getDynamicExpression(dc, selectProperty);
     788        Expression select = ItemContext.getDynamicExpression(dc, tc.getProperty());
    788789        if (select != null)
    789790        {
     
    791792          if (positionIndex == SPOT_AVG)
    792793          {
    793             select = Aggregations.mean(select);
     794            select = tc.getAverageMethod().getAverageExpression(select);
    794795          }
    795796          spotQuery.select(Selects.expression(select, "e" + i));
     
    809810        if (positionIndex == SPOT_AVG)
    810811        {
    811           sortby = Aggregations.mean(sortby);
     812          // Find TableColumn to know which average method to use
     813          boolean found = false;
     814          for (TableColumn tc : selectionList)
     815          {
     816            if (sortProperty.equals(tc.getProperty()))
     817            {
     818              sortby = tc.getAverageMethod().getAverageExpression(sortby);
     819              found = true;
     820              break;
     821            }
     822          }
     823          if (!found) sortby = null;
    812824        }
    813825        if (sortby != null)
  • branches/webservices/src/clients/web/net/sf/basedb/clients/web/PermissionUtil.java

    r2916 r3581  
    203203  }
    204204 
     205  public static String translatePermissionsToString(Set<Permission> permissions)
     206  {
     207    StringBuilder permissionString = new StringBuilder();
     208    permissionString.append(permissions.contains(Permission.READ) ? "R" : "");
     209    permissionString.append(permissions.contains(Permission.USE) ? "U" : "");
     210    permissionString.append(permissions.contains(Permission.WRITE) ? "W" : "");
     211    permissionString.append(permissions.contains(Permission.DELETE) ? "D" : "");
     212    permissionString.append(permissions.contains(Permission.SET_OWNER) ? "O" : "");
     213    permissionString.append(permissions.contains(Permission.SET_PERMISSION) ? "P" : "");
     214    return permissionString.toString();
     215  }
     216 
    205217}
    206218
  • branches/webservices/src/clients/web/net/sf/basedb/clients/web/taglib/table/ColumnDef.java

    r2942 r3581  
    604604          for (int i = 0; i < enumeration.size(); ++i)
    605605          {
    606             String selected = filterValue.equals(enumeration.getKey(i)) ? " selected" : "";
     606            String selected = filterValue.equals(enumeration.getKey(i).trim()) ? " selected" : "";
    607607            sb.append("<option value=\"").append(enumeration.getKey(i)).append("\"").append(selected);
    608608            sb.append(">").append(enumeration.getValue(i)).append("\n");
  • branches/webservices/src/clients/web/net/sf/basedb/clients/web/taglib/table/TableColumn.java

    r3433 r3581  
    2525package net.sf.basedb.clients.web.taglib.table;
    2626
     27import net.sf.basedb.core.Formula;
    2728import net.sf.basedb.core.Type;
    2829import net.sf.basedb.util.formatter.Formatter;
     
    7172  private final boolean exportable;
    7273  private final String show;
    73   private final boolean averagable;
     74  private final Formula.AverageMethod averageMethod;
    7475  private Formatter<?> formatter;
    7576 
     77  /**
     78    Create TableColumn.
     79    @param id
     80    @param property
     81    @param jepExpression
     82    @param datatype
     83    @param title
     84    @param description
     85    @deprecated
     86   */
    7687  public TableColumn(String id, String property, String jepExpression, Type datatype, String title, String description)
    7788  {   
    78     this(id, property, jepExpression, datatype, title, description, "auto", true, true, true, datatype.isNumerical(), null);
     89    this(id, property, jepExpression, datatype, title, description, "auto", true, true, true,
     90      datatype.isNumerical() ? Formula.AverageMethod.ARITHMETIC_MEAN : null, null);
    7991  }
    8092 
    8193  public TableColumn(String id, String property, String jepExpression, Type datatype, String title, String description, String show,
    82     boolean sortable, boolean filterable, boolean exportable, boolean averagable, Formatter<?> formatter)
     94    boolean sortable, boolean filterable, boolean exportable, Formula.AverageMethod averageMethod, Formatter<?> formatter)
    8395  {   
    8496    this.id = id;
     
    92104    this.filterable = filterable;
    93105    this.exportable = exportable;
    94     this.averagable = datatype.isNumerical() && averagable;
     106    this.averageMethod = averageMethod;
    95107    this.formatter = formatter;
    96108  }
     
    148160  public boolean isAveragable()
    149161  {
    150     return averagable;
     162    return averageMethod != null && averageMethod != Formula.AverageMethod.NONE;
    151163  }
    152164
     165  /**
     166    @since 2.4
     167  */
     168  public Formula.AverageMethod getAverageMethod()
     169  {
     170    return averageMethod;
     171  }
     172 
    153173  /**
    154174     @since 2.0.2
  • branches/webservices/src/core/common-queries.xml

    r3533 r3581  
    26672667    <sql>
    26682668      UPDATE FormulaData f
    2669       SET f.averageMethod = 1
     2669      SET f.averageMethod = 2
    26702670      WHERE f.averageMethod IS NULL
    26712671    </sql>
    26722672    <description>
    2673       A HQL query that sets the averageMethod to a for all
     2673      A HQL query that sets the averageMethod to arithmetic mean for all
    26742674      formulas with a null value.
    26752675    </description>
     
    26792679    <sql>
    26802680      UPDATE ExtraValueTypeData evt
    2681       SET evt.averageMethod = 1
     2681      SET evt.averageMethod = 2
    26822682      WHERE evt.averageMethod IS NULL
    26832683    </sql>
    26842684    <description>
    2685       A HQL query that sets the averageMethod to a for all
     2685      A HQL query that sets the averageMethod to arithmetic mean for all
    26862686      extra value types with a null value.
    26872687    </description>
  • branches/webservices/src/core/net/sf/basedb/core/AnnotationBetweenRestriction.java

    r2304 r3581  
    4545    Create a new annotation restriction.
    4646   
     47    @deprecated Use {@link #AnnotationBetweenRestriction(String, AnnotationType, Object, Object, boolean)}
     48      instead with alias=null
     49  */
     50  public AnnotationBetweenRestriction(AnnotationType annotationType, Object lowValue, Object highValue, boolean includeInheriting)
     51    throws InvalidDataException
     52  {
     53    this(null, annotationType, lowValue, highValue, includeInheriting);
     54  }
     55 
     56  /**
     57    Create a new annotation restriction.
     58   
     59    @param alias The alias of a joined item where the annotations are
     60      located or null to use the root entity of the query
    4761    @param annotationType The annotation type to use in the query
    4862    @param lowValue The low value to use in the query, it must be of the
     
    5670    @throws InvalidDataException If any of the parameters are null
    5771      or not follow the rules above.
     72    @since 2.4
    5873  */
    59   public AnnotationBetweenRestriction(AnnotationType annotationType, Object lowValue, Object highValue, boolean includeInheriting)
     74  public AnnotationBetweenRestriction(String alias, AnnotationType annotationType, Object lowValue, Object highValue, boolean includeInheriting)
    6075    throws InvalidDataException
    6176  {
    62     super(annotationType, includeInheriting);
     77    super(alias, annotationType, includeInheriting);
    6378    if (lowValue == null) throw new InvalidUseOfNullException("lowValue");
    6479    if (highValue == null) throw new InvalidUseOfNullException("highValue");
     
    7691    this.highValue = highValue;
    7792  }
     93
    7894
    7995  /*
  • branches/webservices/src/core/net/sf/basedb/core/AnnotationInRestriction.java

    r2304 r3581  
    4646    Create a new annotation restriction.
    4747   
     48    @deprecated Use {@link #AnnotationInRestriction(String, AnnotationType, boolean, Object[])}
     49      instead with alias=null
     50  */
     51  public AnnotationInRestriction(AnnotationType annotationType, boolean includeInheriting, Object... values)
     52    throws InvalidDataException
     53  {
     54    this(null, annotationType, includeInheriting, values);
     55  }
     56
     57  /**
     58    Create a new annotation restriction.
     59   
    4860    @param annotationType The annotation type to use in the query
    4961    @param includeInheriting If items inherting the annotation should be returned
     
    5466    @throws InvalidDataException If any of the parameters are null
    5567      or the array is empty or not follow the rules above.
     68    @since 2.4
    5669  */
    57   public AnnotationInRestriction(AnnotationType annotationType, boolean includeInheriting, Object... values)
     70  public AnnotationInRestriction(String alias, AnnotationType annotationType, boolean includeInheriting, Object... values)
    5871    throws InvalidDataException
    5972  {
    60     super(annotationType, includeInheriting);
     73    super(alias, annotationType, includeInheriting);
    6174    if (values == null || values.length == 0) throw new InvalidUseOfNullException("values");
    6275    for (int i = 0; i < values.length; ++i)
     
    7184    this.values = Arrays.asList(values);
    7285  }
    73 
    7486  /*
    7587    From the AnnotationRestriction class
  • branches/webservices/src/core/net/sf/basedb/core/AnnotationRestriction.java

    r2667 r3581  
    6161  final int annotationTypeId;
    6262  final boolean includeInheriting;
     63  final String alias;
    6364
    6465  /**
     
    6667    @param annotationType The annotation type to use in the query
    6768  */
    68   AnnotationRestriction(AnnotationType annotationType, boolean includeInheriting)
     69  AnnotationRestriction(String alias, AnnotationType annotationType, boolean includeInheriting)
    6970    throws InvalidDataException
    7071  {
     
    7374    this.valueType = annotationType.getValueType();
    7475    this.includeInheriting = includeInheriting;
     76    this.alias = alias;
    7577  }
    7678
     
    8486    @param valueType The type of values for annotations
    8587  */
    86   AnnotationRestriction(int annotationTypeId, Type valueType, boolean includeInheriting)
     88  AnnotationRestriction(String alias, int annotationTypeId, Type valueType, boolean includeInheriting)
    8789    throws InvalidDataException
    8890  {
     
    9193    this.valueType = valueType;
    9294    this.includeInheriting = includeInheriting;
     95    this.alias = alias;
    9396  }
    9497
     
    207210      annotationSetIds = annotationSets.toString();
    208211    }
    209     String hql = query.getRootAlias()+".annotationSet IN ("+annotationSetIds+")";
     212    String hql = (alias == null ? query.getRootAlias() : alias) +
     213      ".annotationSet IN ("+annotationSetIds+")";
    210214    return hql;
    211215  }
  • branches/webservices/src/core/net/sf/basedb/core/AnnotationSimpleRestriction.java

    r2610 r3581  
    4545  /**
    4646    Create a new annotation restriction using a simple expression:
    47     <code>annotation operator value</code>.
     47    <code>annotation operator value</code>. The restriction is applied to
     48    the root element of the query.
    4849   
     50    @deprecated Use {@link #AnnotationSimpleRestriction(String, AnnotationType, Operator, Object, boolean)}
     51      instead with alias=null
     52  */
     53  public AnnotationSimpleRestriction(AnnotationType annotationType, Operator operator, Object value, boolean includeInheriting)
     54    throws InvalidDataException
     55  {
     56    this(null, annotationType, operator, value, includeInheriting);
     57  }
     58
     59  /**
     60    Create a new annotation restriction using a simple expression:
     61    <code>annotation operator value</code>.
     62   
     63    @param alias The alias of a joined item where the annotations are
     64      located or null to use the root entity of the query
    4965    @param annotationType The annotation type to use in the query
    5066    @param operator The operator, it must be one of the expression
     
    5773    @throws InvalidDataException If any of the parameters are null
    5874      or not follow the rules above.
     75    @since 2.4
    5976  */
    60   public AnnotationSimpleRestriction(AnnotationType annotationType, Operator operator, Object value, boolean includeInheriting)
     77  public AnnotationSimpleRestriction(String alias, AnnotationType annotationType, Operator operator, Object value, boolean includeInheriting)
    6178    throws InvalidDataException
    6279  {
    63     super(annotationType, includeInheriting);
     80    super(alias, annotationType, includeInheriting);
    6481    if (operator == null) throw new InvalidUseOfNullException("operator");
    6582    if (value == null) throw new InvalidUseOfNullException("value");
     
    7794  }
    7895
     96 
    7997  /**
    80     Creates a new annotation restriction for a specific <code>valueType     
     98    Creates a new annotation restriction for a specific <code>valueType</code>.
     99    The restriction is applied to the root element of the query.
     100   
     101    @deprecated Use {@link #AnnotationSimpleRestriction(String, int, Type, Operator, Object, boolean)}
     102      instead with alias=null
     103  */
     104  public AnnotationSimpleRestriction(int annotationTypeId, Type valueType, Operator operator, Object value, boolean includeInheriting)
     105    throws InvalidDataException
     106  {
     107    this(null, annotationTypeId, valueType, operator, value, includeInheriting);
     108  }
     109 
     110  /**
     111    Creates a new annotation restriction for a specific <code>valueType</code>.
     112   
     113    @param alias The alias of a joined item where the annotations are
     114      located or null to use the root entity of the query
    81115      @param annotationTypeId the id of the annotation type to use in the query
    82116    @param valueType the type of values for annotations
     
    89123      @throws InvalidDataException If any of the parameters are null
    90124      or not follow the rules above
     125    @since 2.4
    91126  */
    92   public AnnotationSimpleRestriction(int annotationTypeId, Type valueType, Operator operator, Object value, boolean includeInheriting)
     127  public AnnotationSimpleRestriction(String alias, int annotationTypeId, Type valueType, Operator operator, Object value, boolean includeInheriting)
    93128    throws InvalidDataException
    94129  {
    95     super(annotationTypeId, valueType, includeInheriting);
     130    super(alias, annotationTypeId, valueType, includeInheriting);
    96131    if (operator == null) throw new InvalidUseOfNullException("operator");
    97132    if (value == null) throw new InvalidUseOfNullException("value");
  • branches/webservices/src/core/net/sf/basedb/core/ExtendedProperties.java

    r2747 r3581  
    205205      if (type == Type.STRING && length > 255) type = Type.TEXT;
    206206      boolean nullable = XMLUtil.getBooleanAttribute(property, "null", true);
    207       boolean insertable = XMLUtil.getBooleanAttribute(property, "insert", true);;
    208       boolean updateable = XMLUtil.getBooleanAttribute(property, "update", true);;
     207      boolean insertable = XMLUtil.getBooleanAttribute(property, "insert", true);
     208      boolean updateable = XMLUtil.getBooleanAttribute(property, "update", true);
    209209      boolean averagable = XMLUtil.getBooleanAttribute(property, "averagable", type.isNumerical());
     210      String avgMethod = property.getAttributeValue("averagemethod");
     211      Formula.AverageMethod averageMethod = null;
     212      if (avgMethod != null)
     213      {
     214        averageMethod = Formula.AverageMethod.valueOf(avgMethod.toUpperCase());
     215      }
     216      else if (averagable)
     217      {
     218        averageMethod = Formula.AverageMethod.ARITHMETIC_MEAN;
     219      }
     220      else
     221      {
     222        averageMethod = Formula.AverageMethod.NONE;       
     223      }
    210224     
    211225      List<Element> links = (List<Element>)property.getChildren("link");
     
    221235        }
    222236      }
    223       properties.add(new ExtendedProperty(name, title, description, column, type, length, nullable, insertable, updateable, averagable, epLinks));
     237      properties.add(new ExtendedProperty(name, title, description, column, type, length, nullable, insertable, updateable, averageMethod, epLinks));
    224238    }
    225239    return properties;
  • branches/webservices/src/core/net/sf/basedb/core/ExtendedProperty.java

    r3533 r3581  
    4646  private final boolean insertable;
    4747  private final boolean updateable;
    48   private final boolean isAveragable;
     48  private final Formula.AverageMethod averageMethod;
    4949  private final List<ExtendedPropertyLinker> linkers;
    5050
     
    5555  ExtendedProperty(String name, String title, String description, String column,
    5656    Type type, int length, boolean nullable, boolean insertable, boolean updateable,
    57     boolean isAveragable, List<ExtendedPropertyLinker> linkers)
     57    Formula.AverageMethod averageMethod, List<ExtendedPropertyLinker> linkers)
    5858  {
    5959    this.name = name;
     
    6666    this.insertable = insertable;
    6767    this.updateable = updateable;
    68     this.isAveragable = type.isNumerical() && isAveragable;
     68    this.averageMethod = averageMethod;
    6969    this.linkers = linkers;
    7070  }
     
    161161    values. By default all numerical values are averagable.
    162162    @return TRUE if it makes sense to take the average, FALSE otherwise
     163    @see #getAverageMethod()
    163164  */
    164165  public boolean isAveragable()
    165166  {
    166     return isAveragable;
     167    return averageMethod != null && averageMethod != Formula.AverageMethod.NONE;
     168  }
     169 
     170  /**
     171    Which method to use when calculating the average of a set of values.
     172    Prior to 2.4 only arithmetic mean was supported.
     173    @return The average method to use
     174    @since 2.4
     175  */
     176  public Formula.AverageMethod getAverageMethod()
     177  {
     178    return averageMethod;
    167179  }
    168180 
  • branches/webservices/src/core/net/sf/basedb/core/ExtraValueType.java

    r3533 r3581  
    8585    ev.setExternalId(externalId);
    8686    ev.setValueType(valueType);
    87     ev.setAverageMethod(AverageMethod.ARITHMETIC_MEAN);
     87    ev.setAverageMethod(valueType.isNumerical() ? AverageMethod.ARITHMETIC_MEAN : AverageMethod.NONE);
    8888    return ev;
    8989  }
     
    319319    Get the average method for this extra value type.
    320320    @return A {@link AverageMethod} object
     321    @since 2.4
    321322   */
    322323  public Formula.AverageMethod getAverageMethod()
     
    330331      write permission
    331332    @throws InvalidDataException If the averageMethod is null
     333    @since 2.4
    332334  */
    333335  public void setAverageMethod(Formula.AverageMethod averageMethod)
  • branches/webservices/src/core/net/sf/basedb/core/Formula.java

    r3533 r3581  
    181181    Get the average method for this formula.
    182182    @return A {@link AverageMethod} object
    183    */
     183    @since 2.4
     184  */
    184185  public Formula.AverageMethod getAverageMethod()
    185186  {
     
    192193      write permission
    193194    @throws InvalidDataException If the averageMethod is null
     195    @since 2.4
    194196  */
    195197  public void setAverageMethod(Formula.AverageMethod averageMethod)
     
    370372    The average method used for the values of this formula. The average
    371373    is only useful with a {@link Type#COLUMN_EXPRESSION}.
    372    */
     374    @version 2.4
     375  */
    373376  public enum AverageMethod
    374377  {
    375     NONE(0, "None"),
    376     GEOMETRIC_MEAN(1, "Geometric mean"),
    377     ARITHMETIC_MEAN(2, "Arithmetic mean"),
    378     MIN(3, "Min"),
    379     MAX(4, "Max");
     378    NONE(0, "None")
     379    {
     380      public Expression getAverageExpression(Expression e)
     381      {
     382        return null;
     383      }
     384    },
     385    GEOMETRIC_MEAN(1, "Geometric mean")
     386    {
     387      public Expression getAverageExpression(Expression e)
     388      {
     389        return Aggregations.geometricMean(e);
     390      }     
     391    },
     392    ARITHMETIC_MEAN(2, "Arithmetic mean")
     393    {
     394      public Expression getAverageExpression(Expression e)
     395      {
     396        return Aggregations.mean(e);
     397      }
     398     
     399    },
     400    MIN(3, "Min")
     401    {
     402      public Expression getAverageExpression(Expression e)
     403      {
     404        return Aggregations.min(e);
     405      }
     406       
     407    },
     408    MAX(4, "Max")
     409    {
     410      public Expression getAverageExpression(Expression e)
     411      {
     412        return Aggregations.max(e);
     413      }
     414     
     415    };
    380416   
    381417    /**
     
    415451    }
    416452   
    417     public Expression getAverageExpression(Expression e)
    418     {
    419       Expression avg;
    420       switch (this)
    421       {
    422         case GEOMETRIC_MEAN :
    423           avg = Aggregations.geometricMean(e);
    424           break;
    425         case ARITHMETIC_MEAN :
    426           avg = Aggregations.mean(e);
    427           break;
    428         case MIN :
    429           avg = Aggregations.min(e);
    430           break;
    431         case MAX:
    432           avg = Aggregations.max(e);
    433           break;
    434         case NONE:
    435         default:
    436           avg = Expressions.string("");
    437           break;
    438       }
    439 
    440       return avg;
    441     }
    442    
    443     /**
    444      * Get the integer value that is used when storing a
    445      * <code>Formula.AverageMethod</code> in the database.
    446      *
    447      * @return The integer value of this type
    448      */
     453    /**
     454      Given an expression, create an expression that takes the correct
     455      average of it.
     456      @param e The expression, null is not allowed
     457      @return The average expression, or null if it is not possible
     458        to create an average expression
     459    */
     460    public abstract Expression getAverageExpression(Expression e);
     461   
     462    /**
     463      Get the integer value that is used when storing a
     464      <code>Formula.AverageMethod</code> in the database.
     465      @return The integer value of this type
     466    */
    449467    public int getValue()
    450468    {
     
    469487      is typically used to create a root bioassay set from raw data.
    470488    */
    471     INTENSITY_EXPRESSION(1, "Intensity expression", false)
     489    INTENSITY_EXPRESSION(1, "Intensity expression", false, false)
    472490    {
    473491      /**
     
    501519      bioassay set into a child bioassay set.
    502520    */
    503     INTENSITY_TRANSFORMATION(2, "Intensity transformation", false)   
     521    INTENSITY_TRANSFORMATION(2, "Intensity transformation", false, false)   
    504522    {
    505523      /**
     
    543561      The formula can also be used to calculate extra values for a bioassay set.
    544562    */
    545     COLUMN_EXPRESSION(3, "Column expression", true)
     563    COLUMN_EXPRESSION(3, "Column expression", true, true)
    546564    {
    547565      /**
     
    566584      to create a filtered bioassay set.
    567585    */
    568     COLUMN_RESTRICTION(4, "Column restriction", false)
     586    COLUMN_RESTRICTION(4, "Column restriction", false, false)
    569587    {
    570588      /**
     
    613631    private final String displayValue;
    614632    private final boolean canUseColoring;
    615    
    616     private Type(int value, String displayValue, boolean canUseColoring)
     633    private final boolean supportsAverage;
     634   
     635    private Type(int value, String displayValue, boolean canUseColoring, boolean supportsAverage)
    617636    {
    618637      this.value = value;
    619638      this.displayValue = displayValue;
    620639      this.canUseColoring = canUseColoring;
     640      this.supportsAverage = supportsAverage;
    621641    }
    622642   
     
    643663    {
    644664      return canUseColoring;
     665    }
     666   
     667    /**
     668      If a formula of this type can be used in an average expression or not.
     669      This is only possible for formulas which create one value.
     670      @since 2.4
     671    */
     672    public boolean supportsAverage()
     673    {
     674      return supportsAverage;
    645675    }
    646676   
  • branches/webservices/src/core/net/sf/basedb/core/Install.java

    r3533 r3581  
    101101    method.
    102102  */
    103   public static final int NEW_SCHEMA_VERSION = Integer.valueOf(36).intValue();
     103  public static final int NEW_SCHEMA_VERSION = Integer.valueOf(37).intValue();
    104104 
    105105  public static synchronized void createTables(boolean update, final ProgressReporter progress)
     
    605605      createPluginDefinition("net.sf.basedb.plugins.PluginConfigurationImporter", null, null, true, null, false);
    606606      createPluginDefinition("net.sf.basedb.plugins.CdfFileReporterImporter", null, null, true, null, false);
     607      createPluginDefinition("net.sf.basedb.plugins.PackedFileExporter", null, keyEveryoneUse, true, null, true);
    607608     
    608609      // Plugin configurations
  • branches/webservices/src/core/net/sf/basedb/core/PropertyFilter.java

    r3533 r3581  
    183183    Create a restriction from the filter. There are a few special cases:
    184184    <p>
     185    If the property starts with a $ it is interpreted as a <code>alias.property</code>
     186    value, ignoring the root alias of the query. The alias is removed from the
     187    property before proceeding.
     188    <p>
    185189    If the property starts with a # it is a filter on annotations. The rest of
    186190    the property is the ID of the annotation type, and we use a
    187191    {@link AnnotationSimpleRestriction} object for the restriction.
    188     <p>
    189     If the property starts with a $ it is interpreted as a <code>alias.property</code>
    190     value, ignoring the root alias of the query.
    191192    <p>
    192193    If the property starts with a @ the property is a collection of values and
     
    201202    Restriction restriction = null;
    202203    String property = getProperty();
     204    String alias = null;
     205   
     206    if (property != null && property.startsWith("$"))
     207    {
     208      // Property is alias.property or alias only
     209      int dotIndex = property.indexOf(".");
     210      if (dotIndex == -1)
     211      {
     212        // Alias only
     213        alias = property.substring(1);
     214        property = null;
     215      }
     216      else if (property != null)
     217      {
     218        // Alias.property
     219        alias = property.substring(1, dotIndex);
     220        property = property.substring(dotIndex+1);
     221      }
     222    }
    203223   
    204224    if (property != null && property.startsWith("#"))
     
    206226      // Property is id of annotation type: #id
    207227      int annotationTypeId = (Integer)Type.INT.parseString(property.substring(1));
    208       restriction = new AnnotationSimpleRestriction(annotationTypeId, getValueType(),
     228      restriction = new AnnotationSimpleRestriction(alias, annotationTypeId, getValueType(),
    209229        getOperator(), getValueAsObject(), false);
    210230    }
     
    214234      Expression parameter = getValue() == null ? null :
    215235        Expressions.parameter(parameterName, getValueAsObject(), getValueType());
    216       String alias = null;
    217       if (property != null && property.startsWith("$"))
    218       {
    219         // Property is alias.property or alias only
    220         int dotIndex = property.indexOf(".");
    221         if (dotIndex == -1)
    222         {
    223           // Alias only
    224           alias = property.substring(1);
    225           property = null;
    226         }
    227         else if (property != null)
    228         {
    229           // Alias.property
    230           alias = property.substring(1, dotIndex);
    231           property = property.substring(dotIndex+1);
    232         }
    233       }
     236
    234237      if (property != null && property.startsWith("@"))
    235238      {
  • branches/webservices/src/core/net/sf/basedb/core/RawDataProperty.java

    r2535 r3581  
    4242  */
    4343  RawDataProperty(String name, String title, String description, String column,
    44     Type type, int length, boolean nullable, boolean averagable, int channel)
     44    Type type, int length, boolean nullable, Formula.AverageMethod averageMethod, int channel)
    4545  {
    46     super(name, title, description, column, type, length, nullable, true, false, averagable, null);
     46    super(name, title, description, column, type, length, nullable, true, false, averageMethod, null);
    4747    this.channel = channel;
    4848  }
  • branches/webservices/src/core/net/sf/basedb/core/RawDataTypes.java

    r2535 r3581  
    177177      boolean nullable = XMLUtil.getBooleanAttribute(property, "null", true);
    178178      boolean averagable = XMLUtil.getBooleanAttribute(property, "averagable", type.isNumerical());
     179      String avgMethod = property.getAttributeValue("averagemethod");
     180      Formula.AverageMethod averageMethod = null;
     181      if (avgMethod != null)
     182      {
     183        averageMethod = Formula.AverageMethod.valueOf(avgMethod.toUpperCase());
     184      }
     185      else if (averagable)
     186      {
     187        averageMethod = Formula.AverageMethod.ARITHMETIC_MEAN;
     188      }
     189      else
     190      {
     191        averageMethod = Formula.AverageMethod.NONE;       
     192      }
    179193      int channel = XMLUtil.getIntAttribute(property, "channel", 0);
    180       properties.add(new RawDataProperty(name, title, description, column, type, length, nullable, averagable, channel));
     194      properties.add(new RawDataProperty(name, title, description, column, type, length, nullable, averageMethod, channel));
    181195    }
    182196    return properties;
  • branches/webservices/src/core/net/sf/basedb/core/Update.java

    r3533 r3581  
    429429    </td>
    430430  </tr>
     431 
     432  <tr>
     433    <td>37</td>
     434    <td>
     435      <ul>
     436        <li>Implement {@link net.sf.basedb.core.data.ExtendableData} to {@link net.sf.basedb.core.data.UserData}</li>
     437      </ul>
     438      Only the schemaVersion number is increased in this class, the real update work is done when the database is re-build.
     439    </td>
     440  </tr>
    431441
    432442  </table>
     
    613623      }
    614624     
    615       /*
     625     
    616626      if (schemaVersion < 37)
    617627      {
    618628        if (progress != null) progress.display((int)(36*progress_factor), "--Updating schema version: " + schemaVersion + " -> 37...");
    619629        schemaVersion = setSchemaVersionInTransaction(session, 37);
     630      }
     631     
     632      /*
     633      if (schemaVersion < 38)
     634      {
     635        if (progress != null) progress.display((int)(37*progress_factor), "--Updating schema version: " + schemaVersion + " -> 38...");
     636        schemaVersion = setSchemaVersionInTransaction(session, 38);
    620637        - or -
    621         schemaVersion = updateToSchemaVersion37(session);
     638        schemaVersion = updateToSchemaVersion38(session);
    622639      }
    623640      ... etc...
     
    16481665        if (schemaVersion < 36)
    16491666        {
    1650           // Set averageMethod to 1 for all formulas with a null value
     1667          // Set averageMethod to arithmetic mean (=2) for all formulas with a null value
    16511668          org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
    16521669            "SET_AVERAGE_METHOD_ON_FORMULAS");
    16531670          /*
    16541671            UPDATE FormulaData f
    1655             SET f.averageMethod = 1
     1672            SET f.averageMethod = 2
    16561673            WHERE f.averageMethod IS NULL
    16571674          */
    16581675          HibernateUtil.executeUpdate(query);
    16591676         
    1660           // Set averageMethod to 1 for all extravaluetypes with a null value
     1677          // Set averageMethod to arithmetic mean (=2) for all extravaluetypes with a null value
    16611678          query = HibernateUtil.getPredefinedQuery(session,
    16621679            "SET_AVERAGE_METHOD_ON_EXTRAVALUETYPES");
    16631680          /*
    16641681            UPDATE ExtraValueTypeData evt
    1665             SET evt.averageMethod = 1
     1682            SET evt.averageMethod = 2
    16661683            WHERE evt.averageMethod IS NULL
    16671684          */
  • branches/webservices/src/core/net/sf/basedb/core/User.java

    r3533 r3581  
    703703    checkPermission(Permission.RESTRICTED_WRITE);
    704704    getData().setUrl(StringUtil.setNullableString(url, "url", MAX_URL_LENGTH));
     705  }
     706 
     707  /**
     708    Gets an extended property with a certain name
     709    @param name The name of the property
     710    @return An Object or
     711      null if no extended property exists with the name
     712    @since 2.4
     713  */
     714  public Object getExtended(String name)
     715  {
     716    return getData().getExtended(name);
     717  }
     718  /**
     719    Sets an extended property
     720    @param name The name to call the extended property by
     721    @param value The value the extended property should have
     722    @throws PermissionDeniedException If the logged in user doesn't
     723      have @link {Permission#WRITE} permission for the user.
     724    @since 2.4
     725  */
     726  public void setExtended(String name, Object value)
     727  {
     728    checkPermission(Permission.RESTRICTED_WRITE);
     729    getData().setExtended(name, value);
    705730  }
    706731
  • branches/webservices/src/core/net/sf/basedb/core/data/ExtendableData.java

    r2601 r3581  
    4545         update="true"
    4646         insert="true"
    47          averagable="false"
     47         averagemethod="geometric_mean"
    4848         description="An extra property for all reporters"
    4949      /&gt;
     
    156156    <td>averagable</td>
    157157    <td>
     158      <b>This attribute has been deprecated and is replaced by <code>averagemethod</code>!</b>
     159      <br>
    158160      If it makes sense to take the average of multiple values for this
    159161      property. By default all numerical columns are averagable. For non-numerical
    160       columns, this attribute is ignored.
     162      columns, this attribute is ignored. The default method is to calculate the
     163      arithmetic mean.
    161164      <ul>
    162165      <li>true
     
    164167      </ul>
    165168      See {@link net.sf.basedb.core.ExtendedProperty#isAveragable()}.
     169    </td>
     170  </tr>
     171  <tr valign="top">
     172    <td>averagemethod</td>
     173    <td>
     174      The method to use when calculating the average of a set of values.
     175      This attribute replaces the <code>averagable</code> attribute.
     176      The following values can be used:
     177      <ul>
     178      <li>none: do not use this property when calculating averages
     179      <li>arithmetic_mean: calculate the arithmetic mean
     180      <li>geometric_mean: calculate the geometric mean
     181      <li>min: use the minimum value among the values in the set
     182      <li>max: use the maximum value among the values in the set
     183      </ul>
     184      If no value is given to this attribute the default is to use arithmetic
     185      mean for all numerical value types.
     186      See {@link net.sf.basedb.core.ExtendedProperty#getAverageMethod()}.
    166187    </td>
    167188  </tr>
  • branches/webservices/src/core/net/sf/basedb/core/data/ExtraValueTypeData.java

    r3533 r3581  
    134134    The average method for thid formula:
    135135    <ul>
    136     <li>0 = none, {@link net.sf.basedb.core.Formula.AverageMethod#NONE}; no average is defined for this formula
    137     <li>1 = geometric mean, {@link net.sf.basedb.core.Formula.AverageMethod#GEOMETRIC_MEAN}; this formula uses geometric mean
    138     <li>2 = arithmetic mean, {@link net.sf.basedb.core.Formula.AverageMethod#ARITHMETIC_MEAN}; this formula uses arithmetic mean
    139     <li>3 = min, {@link net.sf.basedb.core.Formula.AverageMethod#MIN}; this formula uses the min value as a "mean"
    140     <li>4 = max, {@link net.sf.basedb.core.Formula.AverageMethod#MAX}; this formula uses the max value as a "mean"
     136    <li>0 = none, {@link net.sf.basedb.core.Formula.AverageMethod#NONE};
     137      no average is defined for this formula
     138    <li>1 = geometric mean, {@link net.sf.basedb.core.Formula.AverageMethod#GEOMETRIC_MEAN};
     139      this formula uses geometric mean
     140    <li>2 = arithmetic mean, {@link net.sf.basedb.core.Formula.AverageMethod#ARITHMETIC_MEAN};
     141      this formula uses arithmetic mean
     142    <li>3 = min, {@link net.sf.basedb.core.Formula.AverageMethod#MIN};
     143      this formula uses the min value as a "mean"
     144    <li>4 = max, {@link net.sf.basedb.core.Formula.AverageMethod#MAX};
     145      this formula uses the max value as a "mean"
    141146    </ul>
    142147   
    143148    @hibernate.property column="`average_method`" type="int" not-null="true"
     149    @since 2.4
    144150  */
    145151  public int getAverageMethod()
  • branches/webservices/src/core/net/sf/basedb/core/data/FormulaData.java

    r3533 r3581  
    4848    The average method for thid formula:
    4949    <ul>
    50     <li>0 = none, {@link net.sf.basedb.core.Formula.AverageMethod#NONE}; no average is defined for this formula
    51     <li>1 = geometric mean, {@link net.sf.basedb.core.Formula.AverageMethod#GEOMETRIC_MEAN}; this formula uses geometric mean
    52     <li>2 = arithmetic mean, {@link net.sf.basedb.core.Formula.AverageMethod#ARITHMETIC_MEAN}; this formula uses arithmetic mean
    53     <li>3 = min, {@link net.sf.basedb.core.Formula.AverageMethod#MIN}; this formula uses the min value as a "mean"
    54     <li>4 = max, {@link net.sf.basedb.core.Formula.AverageMethod#MAX}; this formula uses the max value as a "mean"
     50    <li>0 = none, {@link net.sf.basedb.core.Formula.AverageMethod#NONE};
     51      no average is defined for this formula
     52    <li>1 = geometric mean, {@link net.sf.basedb.core.Formula.AverageMethod#GEOMETRIC_MEAN};
     53      this formula uses geometric mean
     54    <li>2 = arithmetic mean, {@link net.sf.basedb.core.Formula.AverageMethod#ARITHMETIC_MEAN};
     55      this formula uses arithmetic mean
     56    <li>3 = min, {@link net.sf.basedb.core.Formula.AverageMethod#MIN};
     57      this formula uses the min value as a "mean"
     58    <li>4 = max, {@link net.sf.basedb.core.Formula.AverageMethod#MAX};
     59      this formula uses the max value as a "mean"
    5560    </ul>
    5661   
    5762    @hibernate.property column="`average_method`" type="int" not-null="true"
     63    @since 2.4
    5864  */
    5965  public int getAverageMethod()
  • branches/webservices/src/core/net/sf/basedb/core/data/UserData.java

    r2962 r3581  
    4141public class UserData
    4242  extends BasicData
    43   implements NameableData, RemovableData, SystemData
     43  implements NameableData, RemovableData, SystemData, ExtendableData
    4444{
    4545
     
    113113  {
    114114    this.systemId = systemId;
     115  }
     116  // -------------------------------------------
     117  /*
     118    From the ExtendableData interface
     119    -------------------------------------------
     120  */
     121  private Map<String, Object> extendedProperties;
     122  /**
     123    @since 2.4
     124  */
     125  public Object getExtended(String name)
     126  {
     127    return extendedProperties == null ? null : extendedProperties.get(name);
     128  }
     129  /**
     130    @since 2.4
     131  */
     132  public void setExtended(String name, Object value)
     133  {
     134    if (extendedProperties == null) extendedProperties = new HashMap<String, Object>();
     135    extendedProperties.put(name, value);
    115136  }
    116137  // -------------------------------------------
  • branches/webservices/src/core/net/sf/basedb/core/dtd/extended-properties.dtd

    r2535 r3581  
    4343  update (true|false) "true"
    4444  averagable (true|false) #IMPLIED
     45  averagemethod (none|arithmetic_mean|geometric_mean|min|max) #IMPLIED
    4546>
    4647
  • branches/webservices/src/core/net/sf/basedb/core/dtd/raw-data-types.dtd

    r2535 r3581  
    4646  null (true|false) "true"
    4747  averagable (true|false) #IMPLIED
     48  averagemethod (none|arithmetic_mean|geometric_mean|min|max) #IMPLIED
    4849  channel CDATA #IMPLIED
    4950>
  • branches/webservices/src/core/net/sf/basedb/core/plugin/AbstractAnalysisPlugin.java

    r3533 r3581  
    2424package net.sf.basedb.core.plugin;
    2525
    26 import java.util.Arrays;
    2726import java.util.Collections;
    28 import java.util.HashSet;
     27import java.util.List;
    2928import java.util.Set;
    3029
     30import net.sf.basedb.core.BioAssay;
    3131import net.sf.basedb.core.BioAssaySet;
    3232import net.sf.basedb.core.DbControl;
     
    5656 
    5757  /**
     58    GuiContext = [Item.BIOASSAYSET, GuiContext.Type.ITEM]
     59    @since 2.4
     60  */
     61  protected static final GuiContext CONTEXT_BIOASSAYSET =
     62    new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM);
     63
     64  /**
     65    GuiContext = [Item.BIOASSAY, GuiContext.Type.LIST]
     66    @since 2.4
     67  */
     68  protected static final GuiContext CONTEXT_BIOASSAYS =
     69    new GuiContext(Item.BIOASSAY, GuiContext.Type.LIST);
     70 
     71  /**
    5872    The default gui contexts where it makes sense to use an analysis plugin.
    5973    Override for the {@link InteractivePlugin#getGuiContexts()} method to
    60     specify other contexts. This set can't be modified.
     74    specify other contexts. This set can't be modified. This set only
     75    includes the {@link #CONTEXT_BIOASSAYSET}.
    6176  */
    6277  protected static final Set<GuiContext> defaultGuiContexts =
    63     Collections.unmodifiableSet(new HashSet<GuiContext>(
    64         Arrays.asList(
    65           new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM),
    66           new GuiContext(Item.BIOASSAY, GuiContext.Type.LIST)
    67         )
    68       ));
     78    Collections.singleton(CONTEXT_BIOASSAYSET);
    6979 
    7080  /**
     
    97107  */
    98108  private PluginParameter<BioAssaySet> sourceParameter = null;
     109 
     110  /**
     111    The bioAssays subset parameter.
     112    To use when working on subset of bioassays in a bioAssaySet
     113    @see #getSourceBioAssaysSubSetParameter(String, String, List<BioAssay>)
     114   */
     115  private PluginParameter<BioAssay> sourceSubSetParameter = null;
    99116 
    100117  /**
     
    126143  }
    127144  /**
    128     Check that the item is a bioassayset.
     145    Check that the item is a bioassayset and that the logged in user has
     146    permission to use the current experiment.
    129147    @return null if the item is a bioassayset, an error message otherwise
    130     @throws PermissionDeniedException If the logged in user dosent have
    131       permission to use the Experiment.
     148    @throws PermissionDeniedException If the logged in user dosen't have
     149      permission to use the Experiment
    132150  */
    133151  public String isInContext(GuiContext context, Object item)
    134152  {
    135153    String message = null;
    136     if (defaultGuiContexts.contains(context))
     154    Experiment e = null;
     155    if (context.equals(CONTEXT_BIOASSAYSET))
    137156    {
    138157      if (item == null)
     
    147166      {
    148167        BioAssaySet bas = (BioAssaySet)item;
    149         Experiment e = bas.getExperiment();
    150         e.checkPermission(Permission.USE);
    151       }
    152     }
     168        e = bas.getExperiment();
     169      }
     170    }
     171    else
     172    {
     173      DbControl dc = sc.newDbControl();
     174      try
     175      {
     176        e = getCurrentExperiment(dc);
     177      }
     178      finally
     179      {
     180        if (dc != null) dc.close();
     181      }
     182    }
     183    if (e != null) e.checkPermission(Permission.USE);
    153184    return message;
    154185  }
     
    178209    }
    179210    return sourceParameter;
     211  }
     212 
     213  protected static final String SOURCE_BIOASSAYS = "source_subset";
     214 
     215  /**
     216    Gets a plugin parameter that asks for a subset of bioassays to use as data source
     217    for the plugin.
     218      @param label The parameter's label. Uses a default value if null.
     219   * @param description Description of the parameter. Uses a default value if null.
     220    @return A plugin parameter
     221    @since 2.4
     222  */
     223  protected PluginParameter<BioAssay> getSourceBioAssaysParameter(String label, String description)
     224  {
     225    if (sourceSubSetParameter == null)
     226    {
     227      if (label == null) label = "Source bioassays";
     228      if (description == null) description = "Select the bioassays that should be filtered. " +
     229          "If no bioassay is selected all will be filtered.";
     230      sourceSubSetParameter = new PluginParameter<BioAssay>
     231        (
     232          SOURCE_BIOASSAYS, label, description,
     233          new ItemParameterType<BioAssay>(BioAssay.class, null, false, 0, null)
     234        );   
     235    }
     236    return sourceSubSetParameter;
    180237  }
    181238 
     
    314371 
    315372  /**
     373    Gets a list of bioassays that were selected from the current bioassay set, to use for the analysis.
     374      @param dc The DbControl to access the database with
     375      @return A list with bioassays or null.
     376      @since 2.4
     377   */
     378  @SuppressWarnings("unchecked")
     379  protected List<BioAssay> getSourceBioAssays(DbControl dc)
     380  {
     381    List<BioAssay> bioAssaySubset = (List<BioAssay>)job.getValues(SOURCE_BIOASSAYS);
     382    if (bioAssaySubset != null)
     383    {
     384      for (BioAssay ba : bioAssaySubset)
     385      {
     386        dc.reattachItem(ba);
     387      }
     388    }
     389    return bioAssaySubset;
     390  }
     391 
     392  /**
    316393    Generate a name for the transformation based on the plugin and it's
    317394    configuration. The name is created by taking the name of the plugin from the
  • branches/webservices/src/core/net/sf/basedb/core/query/Aggregations.java

    r3533 r3581  
    5151    Calculates the geometric mean of all values for an expression: new expression =
    5252    EXP(AVG(LN(e))). Note that this method can handle values less then or equal with
    53     0 due although the mathematical definition of geometric mean doesn't alow it.
     53    0 although the mathematical definition of geometric mean doesn't allow it.
    5454    This is caused by the way that sql handle null values in aggregated operations.
    5555    The geometric mean of the numbers [2, -5, 8] is therefor 4 (because ln(-5) is
     
    6060    @return The new Expression
    6161    @throws InvalidDataException If the expression is null
     62    @since 2.4
    6263  */
    6364  public static Expression geometricMean(Expression e)
  • branches/webservices/src/core/net/sf/basedb/core/query/Annotations.java

    r2304 r3581  
    4242  /**
    4343    Create a restriction that searches for annotations
    44     equal to a given value.
    45     @param annotationType The annotation type to search
    46     @param value The value to search for
    47     @param includeInheriting If items inherting the annotation should be returned
    48       by the query or not
     44    equal to a given value on the root entity of a query.
     45    @param annotationType The annotation type to search
     46    @param value The value to search for
     47    @param includeInheriting If items inherting the annotation should be returned
     48      by the query or not
     49    @deprecated Use {@link #eq(String, AnnotationType, Object, boolean)} instead with alias=null
    4950  */
    5051  public static Restriction eq(AnnotationType annotationType, Object value, boolean includeInheriting)
    5152    throws InvalidDataException
    5253  {
    53     return new AnnotationSimpleRestriction(annotationType, Operator.EQ, value, includeInheriting);
    54   }
    55 
    56   /**
    57     Create a restriction that searches for annotations
    58     not equal to a given value.
    59     @param annotationType The annotation type to search
    60     @param value The value to search for
    61     @param includeInheriting If items inherting the annotation should be returned
    62       by the query or not
     54    return eq(null, annotationType, value, includeInheriting);
     55  }
     56
     57  /**
     58    Create a restriction that searches for annotations
     59    equal to a given value on the root or a joined entity of a
     60    query.
     61   
     62    @param alias The alias of the joined entity or null to use the root element
     63    @param annotationType The annotation type to search
     64    @param value The value to search for
     65    @param includeInheriting If items inherting the annotation should be returned
     66      by the query or not
     67    @since 2.4
     68  */
     69  public static Restriction eq(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     70    throws InvalidDataException
     71  {
     72    return new AnnotationSimpleRestriction(null, annotationType, Operator.EQ, value, includeInheriting);
     73  }
     74 
     75  /**
     76    Create a restriction that searches for annotations
     77    not equal to a given value on the root entity of a query.
     78    @param annotationType The annotation type to search
     79    @param value The value to search for
     80    @param includeInheriting If items inherting the annotation should be returned
     81      by the query or not
     82    @deprecated Use {@link #neq(String, AnnotationType, Object, boolean)} instead with alias=null
    6383  */
    6484  public static Restriction neq(AnnotationType annotationType, Object value, boolean includeInheriting)
    6585    throws InvalidDataException
    6686  {
    67     return new AnnotationSimpleRestriction(annotationType, Operator.NEQ, value, includeInheriting);
    68   }
    69 
    70   /**
    71     Create a restriction that searches for annotations
    72     less than a given value.
    73     @param annotationType The annotation type to search
    74     @param value The value to search for
    75     @param includeInheriting If items inherting the annotation should be returned
    76       by the query or not
     87    return neq(null, annotationType, value, includeInheriting);
     88  }
     89 
     90  /**
     91    Create a restriction that searches for annotations
     92    not equal to a given value on the root or a joined entity of a
     93    query.
     94 
     95    @param alias The alias of the joined entity or null to use the root element
     96    @param annotationType The annotation type to search
     97    @param value The value to search for
     98    @param includeInheriting If items inherting the annotation should be returned
     99      by the query or not
     100    @since 2.4
     101  */
     102  public static Restriction neq(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     103    throws InvalidDataException
     104  {
     105    return new AnnotationSimpleRestriction(alias, annotationType, Operator.NEQ, value, includeInheriting);
     106  }
     107
     108  /**
     109    Create a restriction that searches for annotations
     110    less than a given value on the root entity of a query.
     111    @param annotationType The annotation type to search
     112    @param value The value to search for
     113    @param includeInheriting If items inherting the annotation should be returned
     114      by the query or not
     115    @deprecated Use {@link #lt(String, AnnotationType, Object, boolean)} instead with alias=null
    77116  */
    78117  public static Restriction lt(AnnotationType annotationType, Object value, boolean includeInheriting)
    79118    throws InvalidDataException
    80119  {
    81     return new AnnotationSimpleRestriction(annotationType, Operator.LT, value, includeInheriting);
    82   }
    83 
    84   /**
    85     Create a restriction that searches for annotations
    86     less than or equal to a given value.
    87     @param annotationType The annotation type to search
    88     @param value The value to search for
    89     @param includeInheriting If items inherting the annotation should be returned
    90       by the query or not
     120    return lt(null, annotationType, value, includeInheriting);
     121  }
     122
     123  /**
     124    Create a restriction that searches for annotations
     125    less than a given value on the root or a joined entity of a
     126    query.
     127 
     128    @param alias The alias of the joined entity or null to use the root element
     129    @param annotationType The annotation type to search
     130    @param value The value to search for
     131    @param includeInheriting If items inherting the annotation should be returned
     132      by the query or not
     133    @since 2.4
     134  */
     135  public static Restriction lt(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     136    throws InvalidDataException
     137  {
     138    return new AnnotationSimpleRestriction(alias, annotationType, Operator.LT, value, includeInheriting);
     139  }
     140
     141  /**
     142    Create a restriction that searches for annotations
     143    less than or equal to a given value on the root entity of a query.
     144    @param annotationType The annotation type to search
     145    @param value The value to search for
     146    @param includeInheriting If items inherting the annotation should be returned
     147      by the query or not
     148    @deprecated Use {@link #lteq(String, AnnotationType, Object, boolean)} instead with alias=null
    91149  */
    92150  public static Restriction lteq(AnnotationType annotationType, Object value, boolean includeInheriting)
    93151    throws InvalidDataException
    94152  {
    95     return new AnnotationSimpleRestriction(annotationType, Operator.LTEQ, value, includeInheriting);
    96   }
    97 
    98   /**
    99     Create a restriction that searches for annotations
    100     greater than a given value.
    101     @param annotationType The annotation type to search
    102     @param value The value to search for
    103     @param includeInheriting If items inherting the annotation should be returned
    104       by the query or not
     153    return lteq(null, annotationType, value, includeInheriting);
     154  }
     155
     156  /**
     157    Create a restriction that searches for annotations
     158    less than or equal to a given value on the root or a joined entity of a
     159    query.
     160 
     161    @param alias The alias of the joined entity or null to use the root element
     162    @param annotationType The annotation type to search
     163    @param value The value to search for
     164    @param includeInheriting If items inherting the annotation should be returned
     165      by the query or not
     166    @since 2.4
     167  */
     168  public static Restriction lteq(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     169    throws InvalidDataException
     170  {
     171    return new AnnotationSimpleRestriction(alias, annotationType, Operator.LTEQ, value, includeInheriting);
     172  }
     173
     174  /**
     175    Create a restriction that searches for annotations
     176    greater than a given value on the root entity of a query.
     177    @param annotationType The annotation type to search
     178    @param value The value to search for
     179    @param includeInheriting If items inherting the annotation should be returned
     180      by the query or not
     181    @deprecated Use {@link #gt(String, AnnotationType, Object, boolean)} instead with alias=null
    105182  */
    106183  public static Restriction gt(AnnotationType annotationType, Object value, boolean includeInheriting)
    107184    throws InvalidDataException
    108185  {
    109     return new AnnotationSimpleRestriction(annotationType, Operator.GTEQ, value, includeInheriting);
    110   }
    111 
    112   /**
    113     Create a restriction that searches for annotations
    114     greater than or equal to a given value.
    115     @param annotationType The annotation type to search
    116     @param value The value to search for
    117     @param includeInheriting If items inherting the annotation should be returned
    118       by the query or not
     186    return gt(null, annotationType, value, includeInheriting);
     187  }
     188
     189  /**
     190    Create a restriction that searches for annotations
     191    greater than a given value on the root or a joined entity of a
     192    query.
     193 
     194    @param alias The alias of the joined entity or null to use the root element
     195    @param annotationType The annotation type to search
     196    @param value The value to search for
     197    @param includeInheriting If items inherting the annotation should be returned
     198      by the query or not
     199    @since 2.4
     200  */
     201  public static Restriction gt(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     202    throws InvalidDataException
     203  {
     204    return new AnnotationSimpleRestriction(alias, annotationType, Operator.GTEQ, value, includeInheriting);
     205  }
     206 
     207 
     208  /**
     209    Create a restriction that searches for annotations
     210    greater than or equal to a given value on the root entity of a query.
     211    @param annotationType The annotation type to search
     212    @param value The value to search for
     213    @param includeInheriting If items inherting the annotation should be returned
     214      by the query or not
     215    @deprecated Use {@link #gteq(String, AnnotationType, Object, boolean)} instead with alias=null
    119216  */
    120217  public static Restriction gteq(AnnotationType annotationType, Object value, boolean includeInheriting)
    121218    throws InvalidDataException
    122219  {
    123     return new AnnotationSimpleRestriction(annotationType, Operator.GTEQ, value, includeInheriting);
    124   }
    125 
    126   /**
    127     Create a restriction that searches for annotations
    128     matching a given value.
    129     @param annotationType The annotation type to search
    130     @param value The value to search for
    131     @param includeInheriting If items inherting the annotation should be returned
    132       by the query or not
     220    return gteq(null, annotationType, value, includeInheriting);
     221  }
     222
     223  /**
     224    Create a restriction that searches for annotations
     225    greater than or equal to a given value on the root or a joined entity of a
     226    query.
     227 
     228    @param alias The alias of the joined entity or null to use the root element
     229    @param annotationType The annotation type to search
     230    @param value The value to search for
     231    @param includeInheriting If items inherting the annotation should be returned
     232      by the query or not
     233    @since 2.4
     234  */
     235  public static Restriction gteq(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     236    throws InvalidDataException
     237  {
     238    return new AnnotationSimpleRestriction(alias, annotationType, Operator.GTEQ, value, includeInheriting);
     239  }
     240
     241  /**
     242    Create a restriction that searches for annotations
     243    matching a given value on the root entity of a query.
     244    @param annotationType The annotation type to search
     245    @param value The value to search for
     246    @param includeInheriting If items inherting the annotation should be returned
     247      by the query or not
     248    @deprecated Use {@link #like(String, AnnotationType, Object, boolean)} instead with alias=null
    133249  */
    134250  public static Restriction like(AnnotationType annotationType, Object value, boolean includeInheriting)
    135251    throws InvalidDataException
    136252  {
    137     return new AnnotationSimpleRestriction(annotationType, Operator.LIKE, value, includeInheriting);
    138   }
    139  
    140   /**
    141     Create a restriction that searches for annotations
    142     between two given values. If the end values are included or excluded
     253    return like(null, annotationType, value, includeInheriting);
     254  }
     255
     256  /**
     257    Create a restriction that searches for annotations
     258    matching a given value on the root or a joined entity of a
     259    query.
     260   
     261    @param alias The alias of the joined entity or null to use the root element
     262    @param annotationType The annotation type to search
     263    @param value The value to search for
     264    @param includeInheriting If items inherting the annotation should be returned
     265      by the query or not
     266    @since 2.4
     267  */
     268  public static Restriction like(String alias, AnnotationType annotationType, Object value, boolean includeInheriting)
     269    throws InvalidDataException
     270  {
     271    return new AnnotationSimpleRestriction(alias, annotationType, Operator.LIKE, value, includeInheriting);
     272  }
     273
     274 
     275  /**
     276    Create a restriction that searches for annotations
     277    between two given values on the root entity of a query.
     278    If the end values are included or excluded
    143279    depends on the database.
     280   
    144281    @param annotationType The annotation type to search
    145282    @param lowValue The lower bound
     
    147284    @param includeInheriting If items inherting the annotation should be returned
    148285      by the query or not
     286    @deprecated Use {@link #between(String, AnnotationType, Object, Object, boolean)}
     287      instead with alias=null
    149288  */
    150289  public static Restriction between(AnnotationType annotationType, Object lowValue, Object highValue, boolean includeInheriting)
    151290    throws InvalidDataException
    152291  {
    153     return new AnnotationBetweenRestriction(annotationType, lowValue, highValue, includeInheriting);
    154   }
    155 
    156   /**
    157     Create a restriction that searches for annotations
     292    return between(null, annotationType, lowValue, highValue, includeInheriting);
     293  }
     294
     295  /**
     296    Create a restriction that searches for annotations
     297    between two given values on the root or a joined entity of a
     298    query. If the end values are included or excluded
     299    depends on the database.
     300   
     301    @param alias The alias of the joined entity or null to use the root element
     302    @param annotationType The annotation type to search
     303    @param lowValue The lower bound
     304    @param highValue The higher bound
     305    @param includeInheriting If items inherting the annotation should be returned
     306      by the query or not
     307    @since 2.4
     308  */
     309  public static Restriction between(String alias, AnnotationType annotationType, Object lowValue, Object highValue, boolean includeInheriting)
     310    throws InvalidDataException
     311  {
     312    return new AnnotationBetweenRestriction(alias, annotationType, lowValue, highValue, includeInheriting);
     313  }
     314 
     315  /**
     316    Create a restriction that searches for annotations on the root entity of a query
    158317    equal to any value in a list of given values.
    159318    @param annotationType The annotation type to search
     
    161320      by the query or not
    162321    @param values An array of values
     322    @deprecated Use {@link #in(String, AnnotationType, boolean, Object[])}
     323      instead with alias=null
    163324  */
    164325  public static Restriction in(AnnotationType annotationType, boolean includeInheriting, Object... values)
    165326    throws InvalidDataException
    166327  {
    167     return new AnnotationInRestriction(annotationType, includeInheriting, values);
    168   }
    169 
     328    return in(null, annotationType, includeInheriting, values);
     329  }
     330
     331  /**
     332    Create a restriction that searches for annotations
     333    on the root or a joined entity
     334    equal to any value in a list of given values.
     335   
     336    @param alias The alias of the joined entity or null to use the root element
     337    @param annotationType The annotation type to search
     338    @param includeInheriting If items inherting the annotation should be returned
     339      by the query or not
     340    @param values An array of values
     341    @since 2.4
     342  */
     343  public static Restriction in(String alias, AnnotationType annotationType, boolean includeInheriting, Object... values)
     344    throws InvalidDataException
     345  {
     346    return new AnnotationInRestriction(alias, annotationType, includeInheriting, values);
     347  }
    170348
    171349}
  • branches/webservices/src/core/net/sf/basedb/core/query/GeometricMeanExpression.java

    r3533 r3581  
    3434
    3535  @author Johan Enell
    36   @version 2.0
     36  @version 2.4
    3737  @see Aggregations#geometricMean(Expression)
    3838  @base.modified $Date$
  • branches/webservices/src/core/net/sf/basedb/util/AutoDetectFileFormat.java

    r2648 r3581  
    9191    Map<PluginDefinition, List<PluginConfiguration>> plugins =
    9292      new LinkedHashMap<PluginDefinition, List<PluginConfiguration>>();
    93      
     93   
    9494    List<PluginDefinition> pluginDefs = null;
    9595    if (pluginDef == null)
     
    108108    for (PluginDefinition plugin : pluginDefs)
    109109    {
    110       ItemQuery<PluginConfiguration> configQuery = plugin.getPluginConfigurations();
    111       configQuery.order(Orders.asc(Hql.property("name")));
    112       configQuery.include(Include.MINE, Include.SHARED, Include.IN_PROJECT, Include.OTHERS);
    113 
    114110      List<PluginConfiguration> configs = new LinkedList<PluginConfiguration>();
    115       for (PluginConfiguration config : configQuery.list(dc))
     111      if (!plugin.requiresConfiguration())
    116112      {
    117         AutoDetectingImporter importer = plugin.newInstance(AutoDetectingImporter.class,
    118           null, sc, config, null);
    119         if (currentItem == null || ((InteractivePlugin)importer).isInContext(context, currentItem) == null)
     113        if (checkImportable(sc, plugin, null, file, context, currentItem))
    120114        {
    121           InputStream in = file.getDownloadStream(0);
    122           if (importer.isImportable(in))
     115          configs.add(null);
     116        }
     117      }
     118      if (plugin.supportsConfigurations())
     119      {
     120        ItemQuery<PluginConfiguration> configQuery = plugin.getPluginConfigurations();
     121        configQuery.order(Orders.asc(Hql.property("name")));
     122        configQuery.include(Include.MINE, Include.SHARED, Include.IN_PROJECT, Include.OTHERS);
     123        for (PluginConfiguration config : configQuery.list(dc))
     124        {
     125          if (checkImportable(sc, plugin, config, file, context, currentItem))
    123126          {
    124127            configs.add(config);
    125128          }
     129        }
     130      }
     131      if (configs.size() > 0) plugins.put(plugin, configs);
     132    }
     133    return plugins;
     134  }
     135 
     136  private static boolean checkImportable(SessionControl sc, PluginDefinition plugin,
     137    PluginConfiguration config, File file, GuiContext context, Object currentItem)
     138  {
     139    AutoDetectingImporter importer = null;
     140    boolean canBeUsed = false;
     141    try
     142    {
     143      importer = plugin.newInstance(AutoDetectingImporter.class, null, sc, config, null);
     144      boolean isInContext = true;
     145      if (plugin.isInteractive())
     146      {
     147        try
     148        {
     149          InteractivePlugin ip = (InteractivePlugin)importer;
     150          isInContext = ip.isInContext(context, currentItem) == null;
     151        }
     152        catch (Throwable t)
     153        {
     154          isInContext = false;
     155        }
     156      }
     157      if (isInContext)
     158      {
     159        InputStream in = file.getDownloadStream(0);
     160        try
     161        {
     162          canBeUsed = importer.isImportable(in);
     163        }
     164        catch (Throwable t)
     165        {
     166          canBeUsed = false;
     167        }
     168        finally
     169        {
    126170          try
    127171          {
    128172            in.close();
    129173          }
    130           catch (Exception ex)
     174          catch (Throwable t)
    131175          {}
    132176        }
    133       }
    134       if (configs.size() > 0)
    135       {
    136         plugins.put(plugin, configs);
    137       }
    138       else
    139       {
    140         AutoDetectingImporter importer = plugin.newInstance(AutoDetectingImporter.class,
    141           null, sc, null, null);
    142         if (currentItem == null || ((InteractivePlugin)importer).isInContext(context, currentItem) == null)
    143         {
    144           InputStream in = file.getDownloadStream(0);
    145           if (importer.isImportable(in))
    146           {
    147             plugins.put(plugin, null);
    148           }
    149           try
    150           {
    151             in.close();
    152           }
    153           catch (Exception ex)
    154           {}
    155         }
    156       }
     177      }     
    157178    }
    158     return plugins;
     179    finally
     180    {
     181      if (importer != null) importer.done();
     182    }
     183    return canBeUsed;
    159184  }
     185 
    160186}
  • branches/webservices/src/core/net/sf/basedb/util/ContextUtil.java

    r3533 r3581  
    4444  @author Nicklas
    4545  @version 2.4
    46   @base.modified $Date: $
     46  @base.modified $Date$
    4747*/
    4848public class ContextUtil
     
    7272      if (!plugin.requiresConfiguration())
    7373      {
    74         results.add(new ContextResult(sc, plugin, null, context, currentItem));
    75       }
    76       if (pluginQuery != null && plugin.supportsConfigurations())
     74          results.add(new ContextResult(sc, plugin, null, context, currentItem));
     75      }
     76      if (configQuery != null && plugin.supportsConfigurations())
    7777      {
    7878        configQuery.setParameter("plugin", plugin.getId(), Type.INT);
  • branches/webservices/src/core/net/sf/basedb/util/ShareableUtil.java

    r2389 r3581  
    2424package net.sf.basedb.util;
    2525
     26import net.sf.basedb.core.BaseException;
    2627import net.sf.basedb.core.DbControl;
     28import net.sf.basedb.core.Group;
    2729import net.sf.basedb.core.Item;
     30import net.sf.basedb.core.ItemResultIterator;
     31import net.sf.basedb.core.MultiPermissions;
     32import net.sf.basedb.core.Nameable;
    2833import net.sf.basedb.core.Permission;
    2934import net.sf.basedb.core.PermissionDeniedException;
     35import net.sf.basedb.core.Project;
    3036import net.sf.basedb.core.SharedItem;
    31 import net.sf.basedb.core.MultiPermissions;
    32 import net.sf.basedb.core.BaseException;
     37import net.sf.basedb.core.User;
    3338
     39import java.util.ArrayList;
     40import java.util.Collections;
     41import java.util.HashSet;
     42import java.util.List;
    3443import java.util.Set;
    35 import java.util.HashSet;
    3644
    3745/**
     
    6573    return new MultiPermissions(ss);
    6674  }
     75 
     76  /**
     77    Gets a list with the projects, groups and users(in that order) that
     78    an item is shared to.
     79      @param item The item that is shared
     80      @return A <code>List</code> with items implementing {@link net.sf.basedb.core.Nameable}
     81      @since 2.4
     82  */
     83  public static List<Nameable> getSharedTo(DbControl dc, SharedItem item)
     84  {
     85    List<Nameable> sharees = new ArrayList<Nameable>();
     86    if (item.isShared())
     87    {
     88      MultiPermissions mp = new MultiPermissions(Collections.singleton(item));
     89      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     90      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     91      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     92     
     93      while (projects.hasNext())
     94      {
     95        sharees.add(projects.next());
     96      }   
     97      while (groups.hasNext())
     98      {
     99        sharees.add(groups.next());
     100      }
     101      while (users.hasNext())
     102      {
     103        sharees.add(users.next());
     104      }
     105    }
     106    return sharees;
     107  }
    67108}
  • branches/webservices/src/plugins/core/net/sf/basedb/plugins/Base1PluginExecuter.java

    r3533 r3581  
    9393import java.net.URL;
    9494import java.sql.SQLException;
     95import java.util.AbstractSet;
    9596import java.util.ArrayList;
    9697import java.util.Arrays;
     
    104105import java.util.Map;
    105106import java.util.Set;
     107import java.util.TreeMap;
    106108import java.util.regex.Matcher;
    107109import java.util.regex.Pattern;
     
    744746      Boolean mergeReporters = (Boolean) configuration.getValue(geneAveragesParameter.getName());
    745747     
    746       Map<String, String> parameters = new HashMap<String, String>();
     748      ListMap<String, String> parameters = new ListMap<String, String>();
    747749      for (PluginParameter<?> pp : getJobParametersFromXML(String.valueOf(configuration.getValue(jobParametersParameter.getName()))))
    748750      {
     
    908910    try
    909911    {
    910       List<PluginParameter<?>> p = new ArrayList<PluginParameter<?>>();
    911912      String doctype = "<!DOCTYPE jobparameters SYSTEM \"base1-plugin-configuration-file.dtd\">";
    912913      Document doc = XMLUtil.getValidatedXml(doctype+xml, dtdFile);
     
    923924        }
    924925      });
     926     
     927      TreeMap<Integer, PluginParameter<?>> positionParameter = new TreeMap<Integer, PluginParameter<?>>();
    925928      while (it.hasNext())
    926929      {
    927930        Element e = it.next();
    928931        JobParameter jp = new JobParameter(e);
    929         p.add(jp.getPluginParameter());
    930       }
    931       return p;
     932        if (positionParameter.containsKey(jp.getPosition()))
     933        {
     934          throw new BaseException("Duplicate parameter at position "+jp.getPosition());
     935        }
     936        positionParameter.put(jp.getPosition(), jp.getPluginParameter());
     937      }
     938      return new ArrayList<PluginParameter<?>>(positionParameter.values());
    932939    }
    933940    catch (JDOMException e1)
     
    11471154    ffp.setHeaderRegexp(Pattern.compile("(.*?)\\t(.*)"));
    11481155    ffp.setDataHeaderRegexp(Pattern.compile("%"));
     1156    ffp.setDataFooterRegexp(Pattern.compile("^$"));
    11491157    ffp.setDataSplitterRegexp(Pattern.compile("\\t"));
     1158    ffp.setUseNullIfEmpty(false);
    11501159
    11511160    ffp.setInputStream(stream, Config.getCharset());
     
    14301439
    14311440                // int2 = 10^a / 2^(0.5*m)
    1432                 // int1 = int2  2^m
     1441                // int1 = int2 * 2^m
    14331442                intensities[1] = new Float(Math.pow(10, a) / Math.pow(2, 0.5 * m));
    1434                 intensities[0] = new Float(intensities[1] * Math.pow(2, m));
     1443                intensities[0] = new Float(intensities[1] * Math.pow(2, m));
    14351444              }
    14361445
     
    18481857    }
    18491858  }
     1859 
     1860  private class ListMap<K, V> extends java.util.AbstractMap<K, V>
     1861  {
     1862    private List<K> keys = new ArrayList<K>();
     1863    private List<V> values = new ArrayList<V>();
     1864
     1865    @Override
     1866    public Set<java.util.Map.Entry<K, V>> entrySet()
     1867    {
     1868      throw new UnsupportedOperationException();
     1869    }
     1870
     1871    @Override
     1872    public V put(K key, V value)
     1873    {
     1874      V ret = null;
     1875      int index = keys.indexOf(key);
     1876      if (index == -1)
     1877      {
     1878        keys.add(key);
     1879        values.add(value);
     1880      }
     1881      else
     1882      {
     1883        keys.set(index, key);
     1884        ret = values.set(index, value);
     1885      }
     1886      return ret;
     1887    }
     1888
     1889    @Override
     1890    public V get(Object key)
     1891    {
     1892      if (key == null) throw new NullPointerException();
     1893      int index = keys.indexOf(key);
     1894      V ret = null;
     1895      if (index != -1)
     1896      {
     1897        ret = values.get(index);
     1898      }
     1899      return ret;
     1900    }
     1901
     1902    @Override
     1903    public boolean isEmpty()
     1904    {
     1905      return keys.isEmpty();
     1906    }
     1907
     1908    @Override
     1909    public Set<K> keySet()
     1910    {
     1911      return new AbstractSet<K>()
     1912      {
     1913        @Override
     1914        public Iterator<K> iterator()
     1915        {
     1916          return Collections.unmodifiableList(keys).iterator();
     1917        }
     1918
     1919        @Override
     1920        public int size()
     1921        {
     1922          return keys.size();
     1923        }
     1924      };
     1925    }
     1926   
     1927  }
    18501928
    18511929  private enum Base1JobParameterType
  • branches/webservices/src/plugins/core/net/sf/basedb/plugins/BioAssaySetExporter.java

    r3533 r3581  
    302302  }
    303303 
    304  
    305304  private void exportBaseFileSectionAssays(PrintWriter out, DbControl dc, BioAssaySet bas)
    306305  {
     
    313312    }
    314313    out.println("columns\tid\tname" + annotationString);
    315     out.println("annotationColumns" + annotationString);
     314    out.println("annotationColumns" + (annotationString.length() == 0 ? "\t" : annotationString));
    316315    out.println("%");
    317316    for (BioAssay ba : bas.getBioAssays().list(dc))
     
    329328  }
    330329 
    331  
    332330  private void exportBaseFileSectionHead(PrintWriter out, Map<String, String> parameters)
    333331  {
    334332    out.println("BASEfile");
     333   
    335334    if (!parameters.isEmpty())
    336335    {
    337       Set<String> keys = new HashSet<String>(parameters.keySet());
    338       if (keys.remove("section"))
     336      List<String> keys = new ArrayList<String>(parameters.keySet());
     337      if ("section".equals(keys.get(0)))
    339338      {
    340339        out.println("section\t"+parameters.get("section"));
     340        keys = keys.subList(1, keys.size());
     341      }
     342      else
     343      {
     344        out.println("section\tsettings");
     345      }
     346      if (keys.contains("section"))
     347      {
     348        throw new BaseException("The parameters can't have a parameter 'section' in the middle of the list.");
    341349      }
    342350      for (String key : keys)
     
    447455    }
    448456    out.println();
    449     out.println("count\t" + bas.getNumReporters()); //TODO: count number of column/position
     457    out.println("count\t" + query.count(dc)); //TODO: count number of column/position
    450458    out.println("%");
    451459   
     
    477485    Integer prevPos = null;
    478486    HashMap<Short, String> spotValues = new HashMap<Short, String>();
    479     String reporter = null;
    480487    while (iterator.hasNext())
    481488    {
     
    483490      Integer currentPos = r.getInt(posIndex);
    484491     
    485       if (prevPos != null && !currentPos.equals(prevPos))
    486       {
     492      if (!currentPos.equals(prevPos))
     493      {
     494        // Print spot fields
     495        if (!spotValues.isEmpty())
     496        {
     497          String separator = "";
     498          for (Short col : columnNo)
     499          {
     500            String spot = spotValues.get(col);
     501            if (spot != null)
     502            {
     503              out.print(separator);
     504              out.print(spot);
     505            }
     506            else
     507            {
     508              out.print(tabs);
     509            }
     510            separator = "\t";
     511          }
     512          out.println();
     513          spotValues.clear();
     514        }
     515       
    487516        //Print reporter fields
    488         out.print(reporter);
    489        
    490         //Print spot fields
    491         String separator = "";
    492         for (Short col : columnNo)
    493         {
    494           String spot = spotValues.get(col);
    495           if (spot != null)
    496           {
    497             out.print(separator);
    498             out.print(spot);
    499           }
    500           else
    501           {
    502             out.print(tabs);
    503           }
    504           separator = "\t";
    505         }
    506         out.println();
    507        
    508         reporter = null;
    509         spotValues = new HashMap<Short, String>();
    510       }
    511 
    512       if (reporter == null)
    513       {
    514         reporter = "";
    515517        for (int i = 0; i < reporterIndex.size(); ++i)
    516518        {
    517519          String field = r.getString(reporterIndex.get(i));
    518           reporter += field == null ? "" : field;
    519           reporter += "\t";
     520          out.print((field == null ? "" : field) + "\t");
    520521        }
    521522      }
     
    529530      }
    530531      spotValues.put(r.getShort(colIndex), spot);
    531       prevPos = r.getInt(posIndex);
     532      prevPos = currentPos;
     533    }
     534   
     535    // Print the last spot fields
     536    if (!spotValues.isEmpty())
     537    {
     538      String separator = "";
     539      for (Short col : columnNo)
     540      {
     541        String spot = spotValues.get(col);
     542        if (spot != null)
     543        {
     544          out.print(separator);
     545          out.print(spot);
     546        }
     547        else
     548        {
     549          out.print(tabs);
     550        }
     551        separator = "\t";
     552      }
     553      out.println();
     554      spotValues.clear();
    532555    }
    533556  }
     
    838861    List<QueryItem> items = new ArrayList<QueryItem>();
    839862    items.add(new QueryItem("rep.id", "Reporter (internal id)", "reporter", "rep('id')"));
     863    items.add(new QueryItem("rep.position", "Position", "position", "pos()"));
    840864    items.add(new QueryItem("rep.name", "Reporter Name", "name", "rep('name')"));
    841865    items.add(new QueryItem("rep.externalId", "Reporter ID", "externalId", "rep('externalId')"));
     
    855879  {
    856880    List<QueryItem> items = new ArrayList<QueryItem>();
    857     items.add(new QueryItem("position", "Position", "position", "pos()"));
    858881    int channels = bas.getRawDataType().getChannels();
    859882    for (int channel = 1; channel <= channels; ++channel)
     
    10251048
    10261049
     1050  @Override
    10271051  public Plugin.MainType getMainType()
    10281052  {
     
    10921116  private DbControl dc;
    10931117  private BioAssaySet bas;
     1118  @Override
    10941119  protected void begin(DbControl dc)
    10951120  {
     
    10971122  }
    10981123 
     1124  @Override
    10991125  @SuppressWarnings("unchecked")
    11001126  protected void performExport(ExportOutputStream out, ProgressReporter progress)
     
    11501176  }
    11511177 
     1178  @Override
    11521179  protected void end(boolean success)
    11531180  {
    11541181    this.dc = null;
    11551182  }
     1183 
     1184  @Override
    11561185  protected String getSuccessMessage()
    11571186  {
    11581187    return "Bioassay set '" + bas.getName() + "' exported successfully";
    11591188  }
    1160 
    11611189 
    11621190  @Override
  • branches/webservices/src/plugins/core/net/sf/basedb/plugins/FormulaFilter.java

    r3533 r3581  
    5656import java.util.Arrays;
    5757import java.util.Collection;
     58import java.util.Collections;
    5859import java.util.EnumSet;
    5960import java.util.HashSet;
     
    9293
    9394  private static final Set<Permissions> permissions = new HashSet<Permissions>();
     95  private static final Set<GuiContext> guiContexts = Collections.unmodifiableSet(
     96    new HashSet<GuiContext>(Arrays.asList(CONTEXT_BIOASSAYSET, CONTEXT_BIOASSAYS))
     97  );
    9498
    9599  private RequestInformation configureJob;
     
    208212    -------------------------------------------
    209213  */
     214  @Override
     215  public Set<GuiContext> getGuiContexts()
     216  {
     217    return guiContexts;
     218  }
    210219  public RequestInformation getRequestInformation(GuiContext context, String command)
    211220    throws BaseException
  • branches/webservices/src/test/TestFlatFileParser.java

    r2992 r3581  
    88import net.sf.basedb.util.parser.FlatFileParser;
    99import net.sf.basedb.util.parser.Mapper;
     10import net.sf.basedb.util.parser.FlatFileParser.Line;
    1011
    1112/*
     
    197198    }
    198199  }
     200
     201  public static void testHeaderLine(Line line, String name, String value) throws Exception
     202  {
     203    if (!line.type().equals(FlatFileParser.LineType.HEADER))
     204      throw new Exception("Line is no header: "+line.toString());
     205    if (!line.name().equals(name))
     206      throw new Exception("Cant find name '"+name+"' in line '"+line.line()+"'");
     207    if (!line.value().equals(value))
     208      throw new Exception("Cant find value '"+value+"' in line '"+line.line()+"'");
     209  }
     210
     211  public static void testLine(Line line, String name) throws Exception
     212  {
     213    if (!line.line().equals(name))
     214      throw new Exception("Line '"+line.line()+"' doesnt match '"+name+"'");
     215  }
     216
     217  public static void testSection(Line line, String name) throws Exception
     218  {
     219    if (!line.type().equals(FlatFileParser.LineType.SECTION))
     220      throw new Exception("Line is no section: "+line.toString());
     221    if (!line.name().equals(name))
     222      throw new Exception("Cant find sectionname '"+name+"' in line '"+line.line()+"'");
     223  }
    199224}
  • branches/webservices/www/admin/annotationtypecategories/list_categories.jsp

    r3194 r3581  
    3838  import="net.sf.basedb.core.ItemResultList"
    3939  import="net.sf.basedb.core.ItemContext"
     40  import="net.sf.basedb.core.Nameable"
    4041  import="net.sf.basedb.core.Permission"
    4142  import="net.sf.basedb.core.PluginDefinition"
     
    4748  import="net.sf.basedb.core.plugin.Plugin"
    4849  import="net.sf.basedb.util.Enumeration"
     50  import="net.sf.basedb.util.ShareableUtil"
    4951  import="net.sf.basedb.clients.web.Base"
    5052  import="net.sf.basedb.clients.web.ModeInfo"
     
    5254  import="net.sf.basedb.util.Values"
    5355  import="net.sf.basedb.clients.web.PermissionUtil"
     56  import="java.util.Iterator"
    5457  import="java.util.List"
    5558  import="java.util.Map"
     
    249252        id="permission"
    250253        title="Permission"
     254      />
     255      <tbl:columndef
     256        id="sharedTo"
     257        title="Shared to"
    251258      />
    252259      <tbl:toolbar
     
    440447                  %>
    441448                </tbl:cell>
     449                <tbl:cell column="sharedTo">
     450                  <%
     451                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     452                  while(sharees.hasNext())
     453                  {
     454                    Nameable n = sharees.next();
     455                    if (mode.hasPropertyLink())
     456                    {
     457                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     458                    }
     459                    else
     460                    {
     461                      out.write(HTML.encodeTags(n.getName()));
     462                    }
     463                    out.write(sharees.hasNext() ? ", " : "");
     464                  }
     465                  %>
     466                </tbl:cell>
    442467              </tbl:row>
    443468              <%
  • branches/webservices/www/admin/annotationtypecategories/view_category.jsp

    r2978 r3581  
    2828  import="net.sf.basedb.core.SessionControl"
    2929  import="net.sf.basedb.core.DbControl"
     30  import="net.sf.basedb.core.Group"
    3031  import="net.sf.basedb.core.Include"
    3132  import="net.sf.basedb.core.Item"
    3233  import="net.sf.basedb.core.ItemContext"
    3334  import="net.sf.basedb.core.ItemQuery"
     35  import="net.sf.basedb.core.ItemResultIterator"
    3436  import="net.sf.basedb.core.ItemResultList"
    3537  import="net.sf.basedb.core.AnnotationTypeCategory"
     
    3739  import="net.sf.basedb.core.query.Orders"
    3840  import="net.sf.basedb.core.query.Hql"
     41  import="net.sf.basedb.core.MultiPermissions"
    3942  import="net.sf.basedb.core.Permission"
    4043  import="net.sf.basedb.core.PermissionDeniedException"
     
    4245  import="net.sf.basedb.core.plugin.GuiContext"
    4346  import="net.sf.basedb.core.plugin.Plugin"
     47  import="net.sf.basedb.core.Project"
    4448  import="net.sf.basedb.core.User"
    4549  import="net.sf.basedb.clients.web.Base"
     50  import="net.sf.basedb.clients.web.PermissionUtil"
    4651  import="net.sf.basedb.clients.web.util.HTML"
    4752  import="net.sf.basedb.util.Values"
     53  import="java.util.Collections"
    4854  import="java.util.Map"
     55  import="java.util.Set"
    4956%>
    5057<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    195202            visible="<%=annotationTypeCategory.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
    196203          <base:icon image="shared.gif"
    197             visible="<%=annotationTypeCategory.isShared()%>"> This item is shared to other user, groups and/or projects</base:icon>
     204            visible="<%=annotationTypeCategory.isShared()%>"> This item is shared to other users, groups and/or projects</base:icon>
    198205        </div>
    199206        <%
     
    276283        </tbl:table>
    277284        <%
     285      }     
     286     
     287      // Tables with users/groups/projects that this item is shared to
     288      MultiPermissions mp = new MultiPermissions(Collections.singleton(annotationTypeCategory));
     289      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     290      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     291      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     292     
     293      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     294      {
     295        %>
     296        <h4 class="docked">Shared to</h4>
     297        <tbl:table
     298          id="itemsSharedTo"
     299          clazz="itemlist"
     300          columns="all"
     301        >
     302          <tbl:columndef
     303            id="itemType"
     304            title="Item type"
     305          />
     306          <tbl:columndef
     307            id="name"
     308            title="Name"
     309          />
     310          <tbl:columndef
     311            id="permissions"
     312            title="Permissions"
     313          />
     314          <tbl:data>
     315            <tbl:columns>
     316            </tbl:columns>
     317            <tbl:rows>
     318            <%
     319            while(projects.hasNext())
     320            {
     321              Project project = projects.next();
     322              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     323              %>     
     324              <tbl:row>
     325                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     326                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     327                <tbl:cell column="permissions">
     328                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     329                </tbl:cell>
     330              </tbl:row>
     331              <%
     332            }
     333            while(groups.hasNext())
     334            {
     335              Group group = groups.next();
     336              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     337              %>
     338              <tbl:row>             
     339                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     340                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     341                <tbl:cell column="permissions">
     342                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     343                </tbl:cell>
     344              </tbl:row>
     345              <% 
     346            }
     347            while (users.hasNext())
     348            {
     349              User user = users.next();
     350              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     351              %>
     352              <tbl:row>             
     353                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     354                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     355                <tbl:cell column="permissions">
     356                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     357                </tbl:cell>
     358              </tbl:row>
     359              <%
     360            }
     361            %>
     362            </tbl:rows>
     363          </tbl:data>
     364        </tbl:table>
     365        <%
     366      }
     367      else
     368      {
     369        %>
     370        <h4>Shared to</h4>
     371        This annotation type category is not shared
     372        (or, you don't have permission to view the ones it is shared to).
     373        <%
    278374      }
    279375      %>
  • branches/webservices/www/admin/annotationtypes/list_annotationtypes.jsp

    r3533 r3581  
    3838  import="net.sf.basedb.core.ItemResultList"
    3939  import="net.sf.basedb.core.ItemContext"
     40  import="net.sf.basedb.core.Nameable"
    4041  import="net.sf.basedb.core.Permission"
    4142  import="net.sf.basedb.core.PluginDefinition"
     
    4748  import="net.sf.basedb.core.plugin.Plugin"
    4849  import="net.sf.basedb.util.Enumeration"
     50  import="net.sf.basedb.util.ShareableUtil"
    4951  import="net.sf.basedb.clients.web.Base"
    5052  import="net.sf.basedb.clients.web.PermissionUtil"
     
    5254  import="net.sf.basedb.clients.web.util.HTML"
    5355  import="net.sf.basedb.util.Values"
     56  import="java.util.Iterator"
    5457  import="java.util.List"
    5558  import="java.util.Map"
     
    352355        id="permission"
    353356        title="Permission"
     357      />
     358      <tbl:columndef
     359        id="sharedTo"
     360        title="Shared to"
    354361      />
    355362      <tbl:toolbar
     
    561568                  %>
    562569                </tbl:cell>
     570                <tbl:cell column="sharedTo">
     571                  <%
     572                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     573                  while(sharees.hasNext())
     574                  {
     575                    Nameable n = sharees.next();
     576                    if (mode.hasPropertyLink())
     577                    {
     578                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     579                    }
     580                    else
     581                    {
     582                      out.write(HTML.encodeTags(n.getName()));
     583                    }
     584                    out.write(sharees.hasNext() ? ", " : "");
     585                  }
     586                  %>
     587                </tbl:cell>
    563588              </tbl:row>
    564589              <%
  • branches/webservices/www/admin/annotationtypes/view_annotationtype.jsp

    r2978 r3581  
    3939  import="net.sf.basedb.core.ItemQuery"
    4040  import="net.sf.basedb.core.ItemResultList"
     41  import="net.sf.basedb.core.ItemResultIterator"
     42  import="net.sf.basedb.core.MultiPermissions"
     43  import="net.sf.basedb.core.Group"
     44  import="net.sf.basedb.core.Project"
    4145  import="net.sf.basedb.core.PermissionDeniedException"
    4246  import="net.sf.basedb.core.PluginDefinition"
     
    5256  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
    5357  import="java.util.Map"
     58  import="java.util.Collections"
    5459  import="java.util.Date"
     60  import="java.util.Set"
    5561%>
    5662<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    203209            visible="<%=annotationType.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
    204210          <base:icon image="shared.gif"
    205             visible="<%=annotationType.isShared()%>"> This item is shared to other user, groups and/or projects</base:icon>
     211            visible="<%=annotationType.isShared()%>"> This item is shared to other users, groups and/or projects</base:icon>
    206212        </div>
    207213        <%
     
    310316        <%
    311317      }
     318
     319      // Tables with users/groups/projects that this item is shared to
     320      MultiPermissions mp = new MultiPermissions(Collections.singleton(annotationType));
     321      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     322      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     323      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     324     
     325      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     326      {
     327        %>
     328        <h4 class="docked">Shared to</h4>
     329        <tbl:table
     330          id="itemsSharedTo"
     331          clazz="itemlist"
     332          columns="all"
     333        >
     334          <tbl:columndef
     335            id="itemType"
     336            title="Item type"
     337          />
     338          <tbl:columndef
     339            id="name"
     340            title="Name"
     341          />
     342          <tbl:columndef
     343            id="permissions"
     344            title="Permissions"
     345          />
     346          <tbl:data>
     347            <tbl:columns>
     348            </tbl:columns>
     349            <tbl:rows>
     350            <%
     351            while(projects.hasNext())
     352            {
     353              Project project = projects.next();
     354              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     355              %>     
     356              <tbl:row>
     357                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     358                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     359                <tbl:cell column="permissions">
     360                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     361                </tbl:cell>
     362              </tbl:row>
     363              <%
     364            }
     365            while(groups.hasNext())
     366            {
     367              Group group = groups.next();
     368              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     369              %>
     370              <tbl:row>             
     371                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     372                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     373                <tbl:cell column="permissions">
     374                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     375                </tbl:cell>
     376              </tbl:row>
     377              <% 
     378            }
     379            while (users.hasNext())
     380            {
     381              User user = users.next();
     382              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     383              %>
     384              <tbl:row>             
     385                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     386                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     387                <tbl:cell column="permissions">
     388                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     389                </tbl:cell>
     390              </tbl:row>
     391              <%
     392            }
     393            %>
     394            </tbl:rows>
     395          </tbl:data>
     396        </tbl:table>
     397        <%
     398      }
     399      else
     400      {
     401        %>
     402        <h4>Shared to</h4>
     403        This annotation type is not shared
     404        (or, you don't have permission to view the ones it is shared to).
     405        <%
     406      }
    312407      %>
    313408     
  • branches/webservices/www/admin/clients/list_clients.jsp

    r3194 r3581  
    3535  import="net.sf.basedb.core.ItemResultList"
    3636  import="net.sf.basedb.core.ItemContext"
     37  import="net.sf.basedb.core.Nameable"
    3738  import="net.sf.basedb.core.Permission"
    3839  import="net.sf.basedb.core.PluginDefinition"
     
    4243  import="net.sf.basedb.core.plugin.Plugin"
    4344  import="net.sf.basedb.util.Enumeration"
     45  import="net.sf.basedb.util.ShareableUtil"
    4446  import="net.sf.basedb.clients.web.Base"
    4547  import="net.sf.basedb.clients.web.PermissionUtil"
     
    4749  import="net.sf.basedb.clients.web.util.HTML"
    4850  import="net.sf.basedb.util.Values"
     51  import="java.util.Iterator"
    4952  import="java.util.List"
    5053  import="java.util.Map"
     
    240243        id="permission"
    241244        title="Permission"
     245      />
     246      <tbl:columndef
     247        id="sharedTo"
     248        title="Shared to"
    242249      />
    243250      <tbl:toolbar
     
    410417                <tbl:cell column="description"><%=HTML.encodeTags(item.getDescription())%></tbl:cell>
    411418                <tbl:cell column="permission"><%=PermissionUtil.getShortPermissions(item)%></tbl:cell>
     419                <tbl:cell column="sharedTo">
     420                  <%
     421                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     422                  while(sharees.hasNext())
     423                  {
     424                    Nameable n = sharees.next();
     425                    if (mode.hasPropertyLink())
     426                    {
     427                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     428                    }
     429                    else
     430                    {
     431                      out.write(HTML.encodeTags(n.getName()));
     432                    }
     433                    out.write(sharees.hasNext() ? ", " : "");
     434                  }
     435                  %>
     436                </tbl:cell>
    412437              </tbl:row>
    413438              <%
  • branches/webservices/www/admin/clients/view_client.jsp

    r2978 r3581  
    2929  import="net.sf.basedb.core.DbControl"
    3030  import="net.sf.basedb.core.SystemItems"
     31  import="net.sf.basedb.core.Group"
    3132  import="net.sf.basedb.core.Item"
    3233  import="net.sf.basedb.core.ItemContext"
     34  import="net.sf.basedb.core.ItemResultIterator"
    3335  import="net.sf.basedb.core.Permission"
    3436  import="net.sf.basedb.core.Client"
    3537  import="net.sf.basedb.core.User"
     38  import="net.sf.basedb.core.MultiPermissions"
    3639  import="net.sf.basedb.core.PermissionDeniedException"
    3740  import="net.sf.basedb.core.PluginDefinition"
    3841  import="net.sf.basedb.core.plugin.GuiContext"
    3942  import="net.sf.basedb.core.plugin.Plugin"
     43  import="net.sf.basedb.core.Project"
    4044  import="net.sf.basedb.clients.web.Base"
    4145  import="net.sf.basedb.clients.web.PermissionUtil"
    4246  import="net.sf.basedb.clients.web.util.HTML"
    4347  import="net.sf.basedb.util.Values"
     48  import="java.util.Collections"
    4449  import="java.util.Map"
     50  import="java.util.Set"
    4551%>
    4652<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    7379  %>
    7480  <base:page title="<%=title%>">
    75   <base:head scripts="tabcontrol.js" styles="toolbar.css,headertabcontrol.css,path.css">
     81  <base:head scripts="table.js,tabcontrol.js" styles="table.css,toolbar.css,headertabcontrol.css,path.css">
    7682    <script language="JavaScript">
    7783    function editItem()
     
    207213            visible="<%=client.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
    208214          <base:icon image="shared.gif"
    209             visible="<%=client.isShared()%>"> This item is shared to other user, groups and/or projects</base:icon>
     215            visible="<%=client.isShared()%>"> This item is shared to other users, groups and/or projects</base:icon>
    210216        </div>
    211217        <%
    212218      }
    213219      %>
    214       <table class="form" cellspacing=0>
     220      <table class="form" cellspacing="0">
    215221      <tr>
    216222        <td class="prompt">Name</td>
     
    230236      </tr>
    231237      </table>
     238      <%
     239      // Tables with users/groups/projects that this item is shared to
     240      MultiPermissions mp = new MultiPermissions(Collections.singleton(client));
     241      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     242      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     243      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     244     
     245      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     246      {
     247        %>
     248        <h4 class="docked">Shared to</h4>
     249        <tbl:table
     250          id="itemsSharedTo"
     251          clazz="itemlist"
     252          columns="all"
     253        >
     254          <tbl:columndef
     255            id="itemType"
     256            title="Item type"
     257          />
     258          <tbl:columndef
     259            id="name"
     260            title="Name"
     261          />
     262          <tbl:columndef
     263            id="permissions"
     264            title="Permissions"
     265          />
     266          <tbl:data>
     267            <tbl:columns>
     268            </tbl:columns>
     269            <tbl:rows>
     270            <%
     271            while(projects.hasNext())
     272            {
     273              Project project = projects.next();
     274              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     275              %>     
     276              <tbl:row>
     277                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     278                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     279                <tbl:cell column="permissions">
     280                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     281                </tbl:cell>
     282              </tbl:row>
     283              <%
     284            }
     285            while(groups.hasNext())
     286            {
     287              Group group = groups.next();
     288              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     289              %>
     290              <tbl:row>             
     291                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     292                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     293                <tbl:cell column="permissions">
     294                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     295                </tbl:cell>
     296              </tbl:row>
     297              <% 
     298            }
     299            while (users.hasNext())
     300            {
     301              User user = users.next();
     302              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     303              %>
     304              <tbl:row>             
     305                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     306                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     307                <tbl:cell column="permissions">
     308                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     309                </tbl:cell>
     310              </tbl:row>
     311              <%
     312            }
     313            %>
     314            </tbl:rows>
     315          </tbl:data>
     316        </tbl:table>
     317        <%
     318      }
     319      else
     320      {
     321        %>
     322        <h4>Shared to</h4>
     323        This client is not shared
     324        (or, you don't have permission to view the ones it is shared to).
     325        <%
     326      }
     327      %>
    232328     
    233329    </div>
  • branches/webservices/www/admin/extravaluetypes/edit_extravaluetype.jsp

    r2978 r3581  
    3434  import="net.sf.basedb.core.Permission"
    3535  import="net.sf.basedb.core.ExtraValueType"
     36  import="net.sf.basedb.core.Formula"
    3637  import="net.sf.basedb.core.Coloring"
    3738  import="net.sf.basedb.core.PermissionDeniedException"
     
    5556  ExtraValueType extraValueType = null;
    5657  Coloring coloring = null;
     58  Formula.AverageMethod currentAverageMethod = null;
    5759
    5860  if (itemId == 0)
     
    6062    title = "Create extra value type";
    6163    cc.removeObject("item");
     64    currentAverageMethod = Formula.AverageMethod.fromValue(Values.getInt(cc.getPropertyValue("averageMethod"),
     65      Formula.AverageMethod.ARITHMETIC_MEAN.getValue()));
    6266    coloring = new Coloring();
    6367    coloring.setUsingColors(Values.getBoolean(cc.getPropertyValue("coloring.usingColors")));
     
    7074  {
    7175    extraValueType = ExtraValueType.getById(dc, itemId);
     76    currentAverageMethod = extraValueType.getAverageMethod();
    7277    coloring = extraValueType.getColoring();
    7378    cc.setObject("item", extraValueType);
     
    199204
    200205    <h3 class="docked"><%=title%> <base:help tabcontrol="settings" /></h3>
    201     <t:tabcontrol id="settings" contentstyle="<%="height: "+(int)(scale*200)+"px;"%>"
     206    <t:tabcontrol id="settings" contentstyle="<%="height: "+(int)(scale*240)+"px;"%>"
    202207      position="bottom" remember="<%=extraValueType != null%>">
    203208    <t:tab id="info" title="Extra value type" validate="validateExtraValueType()"
     
    242247          }
    243248          %>
     249        </td>
     250      </tr>
     251      <tr>
     252        <td class="prompt">Avg. method</td>
     253        <td>
     254          <select name="averageMethod" class="required">
     255          <%
     256          for (Formula.AverageMethod method : Formula.AverageMethod.values())
     257          {
     258            String selected = method == currentAverageMethod ? "selected" : "";
     259            %>
     260            <option value="<%=method.name()%>" <%=selected%>><%=HTML.encodeTags(method.toString())%>
     261            <%
     262          }
     263          %>
     264          </select>
    244265        </td>
    245266      </tr>
  • branches/webservices/www/admin/extravaluetypes/index.jsp

    r2978 r3581  
    3232  import="net.sf.basedb.core.Include"
    3333  import="net.sf.basedb.core.ExtraValueType"
     34  import="net.sf.basedb.core.Formula"
    3435  import="net.sf.basedb.core.Coloring"
    3536  import="net.sf.basedb.core.ItemQuery"
     
    143144    extraValueType.setDescription(Values.getStringOrNull(request.getParameter("description")));
    144145    extraValueType.setExternalId(externalId);
     146    extraValueType.setAverageMethod(Formula.AverageMethod.valueOf(request.getParameter("averageMethod")));
    145147    Coloring coloring = extraValueType.getColoring();
    146148    coloring.setUsingColors(Values.getBoolean(request.getParameter("use_colors")));
  • branches/webservices/www/admin/extravaluetypes/list_extravaluetypes.jsp

    r3194 r3581  
    3131  import="net.sf.basedb.core.Item"
    3232  import="net.sf.basedb.core.ExtraValueType"
     33  import="net.sf.basedb.core.Formula"
    3334  import="net.sf.basedb.core.ItemQuery"
    3435  import="net.sf.basedb.core.Include"
     
    5859
    5960  private static final Enumeration<String, String> valueTypes = new Enumeration<String, String>();
     61  private static final Enumeration<String, String> avgMethods = new Enumeration<String, String>();
    6062  static
    6163  {
     
    6365    valueTypes.add(Integer.toString(Type.FLOAT.getValue()), Type.FLOAT.toString());
    6466    valueTypes.add(Integer.toString(Type.STRING.getValue()), Type.STRING.toString());
     67    for (Formula.AverageMethod m : Formula.AverageMethod.values())
     68    {
     69      avgMethods.add(Integer.toString(m.getValue()), HTML.encodeTags(m.toString()));
     70    }
    6571  }
    6672
     
    213219        title="Value type"
    214220        enumeration="<%=valueTypes%>"
     221        sortable="true"
     222        filterable="true"
     223        exportable="true"
     224      />
     225      <tbl:columndef
     226        id="averageMethod"
     227        property="averageMethod"
     228        datatype="int"
     229        enumeration="<%=avgMethods%>"
     230        title="Avg. method"
    215231        sortable="true"
    216232        filterable="true"
     
    414430                <tbl:cell column="externalId"><%=HTML.encodeTags(item.getExternalId())%></tbl:cell>
    415431                <tbl:cell column="valueType"><%=item.getValueType()%></tbl:cell>
     432                <tbl:cell column="averageMethod"><%=item.getAverageMethod().toString()%></tbl:cell>
    416433                <tbl:cell column="useColors"><%=item.getColoring().isUsingColors() ? "yes" : "no"%></tbl:cell>
    417434                <tbl:cell column="logarithmic"><%=item.getColoring().isLogarithmic() ? "yes" : "no"%></tbl:cell>
  • branches/webservices/www/admin/extravaluetypes/view_extravaluetype.jsp

    r2978 r3581  
    182182      </tr>
    183183      <tr>
     184        <td class="prompt">Avg. method</td>
     185        <td><%=extraValueType.getAverageMethod().toString()%></td>
     186      </tr>
     187      <tr>
    184188        <td class="prompt">Use coloring</td>
    185189        <td>
  • branches/webservices/www/admin/hardware/list_hardware.jsp

    r3194 r3581  
    3636  import="net.sf.basedb.core.ItemResultList"
    3737  import="net.sf.basedb.core.ItemContext"
     38  import="net.sf.basedb.core.Nameable"
    3839  import="net.sf.basedb.core.Permission"
    3940  import="net.sf.basedb.core.PluginDefinition"
     
    4344  import="net.sf.basedb.core.plugin.Plugin"
    4445  import="net.sf.basedb.util.Enumeration"
     46  import="net.sf.basedb.util.ShareableUtil"
    4547  import="net.sf.basedb.clients.web.Base"
    4648  import="net.sf.basedb.clients.web.PermissionUtil"
     
    4850  import="net.sf.basedb.clients.web.util.HTML"
    4951  import="net.sf.basedb.util.Values"
     52  import="java.util.Iterator"
    5053  import="java.util.List"
    5154  import="java.util.Map"
     
    264267        id="permission"
    265268        title="Permission"
     269      />
     270      <tbl:columndef
     271        id="sharedTo"
     272        title="Shared to"
    266273      />
    267274      <tbl:toolbar
     
    441448                <tbl:cell column="description"><%=HTML.encodeTags(item.getDescription())%></tbl:cell>
    442449                <tbl:cell column="permission"><%=PermissionUtil.getShortPermissions(item)%></tbl:cell>
     450                <tbl:cell column="sharedTo">
     451                  <%
     452                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     453                  while(sharees.hasNext())
     454                  {
     455                    Nameable n = sharees.next();
     456                    if (mode.hasPropertyLink())
     457                    {
     458                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     459                    }
     460                    else
     461                    {
     462                      out.write(HTML.encodeTags(n.getName()));
     463                    }
     464                    out.write(sharees.hasNext() ? ", " : "");
     465                  }
     466                  %>
     467                </tbl:cell>
    443468              </tbl:row>
    444469              <%
  • branches/webservices/www/admin/hardware/view_hardware.jsp

    r2978 r3581  
    2929  import="net.sf.basedb.core.DbControl"
    3030  import="net.sf.basedb.core.SystemItems"
     31  import="net.sf.basedb.core.Group"
    3132  import="net.sf.basedb.core.Item"
    3233  import="net.sf.basedb.core.ItemContext"
     34  import="net.sf.basedb.core.ItemResultIterator"
    3335  import="net.sf.basedb.core.Permission"
    3436  import="net.sf.basedb.core.Hardware"
    3537  import="net.sf.basedb.core.HardwareType"
    3638  import="net.sf.basedb.core.User"
     39  import="net.sf.basedb.core.MultiPermissions"
    3740  import="net.sf.basedb.core.PermissionDeniedException"
    3841  import="net.sf.basedb.core.PluginDefinition"
    3942  import="net.sf.basedb.core.plugin.GuiContext"
    4043  import="net.sf.basedb.core.plugin.Plugin"
     44  import="net.sf.basedb.core.Project"
    4145  import="net.sf.basedb.clients.web.Base"
    4246  import="net.sf.basedb.clients.web.PermissionUtil"
    4347  import="net.sf.basedb.clients.web.util.HTML"
    4448  import="net.sf.basedb.util.Values"
     49  import="java.util.Collections"
    4550  import="java.util.Map"
     51  import="java.util.Set"
    4652%>
    4753<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    7480  %>
    7581  <base:page title="<%=title%>">
    76   <base:head scripts="tabcontrol.js" styles="toolbar.css,headertabcontrol.css,path.css">
     82  <base:head scripts="table,js,tabcontrol.js" styles="table.css,toolbar.css,headertabcontrol.css,path.css">
    7783    <script language="JavaScript">
    7884    function editItem()
     
    193199            visible="<%=hardware.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
    194200          <base:icon image="shared.gif"
    195             visible="<%=hardware.isShared()%>"> This item is shared to other user, groups and/or projects</base:icon>
     201            visible="<%=hardware.isShared()%>"> This item is shared to other users, groups and/or projects</base:icon>
    196202        </div>
    197203        <%
     
    220226      </tr>
    221227      </table>
     228      <%     
    222229     
     230      // Tables with users/groups/projects that this item is shared to
     231      MultiPermissions mp = new MultiPermissions(Collections.singleton(hardware));
     232      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     233      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     234      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     235     
     236      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     237      {
     238        %>
     239        <h4 class="docked">Shared to</h4>
     240        <tbl:table
     241          id="itemsSharedTo"
     242          clazz="itemlist"
     243          columns="all"
     244        >
     245          <tbl:columndef
     246            id="itemType"
     247            title="Item type"
     248          />
     249          <tbl:columndef
     250            id="name"
     251            title="Name"
     252          />
     253          <tbl:columndef
     254            id="permissions"
     255            title="Permissions"
     256          />
     257          <tbl:data>
     258            <tbl:columns>
     259            </tbl:columns>
     260            <tbl:rows>
     261            <%
     262            while(projects.hasNext())
     263            {
     264              Project project = projects.next();
     265              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     266              %>     
     267              <tbl:row>
     268                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     269                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     270                <tbl:cell column="permissions">
     271                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     272                </tbl:cell>
     273              </tbl:row>
     274              <%
     275            }
     276            while(groups.hasNext())
     277            {
     278              Group group = groups.next();
     279              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     280              %>
     281              <tbl:row>             
     282                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     283                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     284                <tbl:cell column="permissions">
     285                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     286                </tbl:cell>
     287              </tbl:row>
     288              <% 
     289            }
     290            while (users.hasNext())
     291            {
     292              User user = users.next();
     293              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     294              %>
     295              <tbl:row>             
     296                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     297                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     298                <tbl:cell column="permissions">
     299                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     300                </tbl:cell>
     301              </tbl:row>
     302              <%
     303            }
     304            %>
     305            </tbl:rows>
     306          </tbl:data>
     307        </tbl:table>
     308        <%
     309      }
     310      else
     311      {
     312        %>
     313        <h4>Shared to</h4>
     314        This hardware is not shared
     315        (or, you don't have permission to view the ones it is shared to).
     316        <%
     317      }
     318      %>
    223319    </div>
    224320      </t:tab>
  • branches/webservices/www/admin/jobagents/list_agents.jsp

    r3194 r3581  
    3535  import="net.sf.basedb.core.ItemResultList"
    3636  import="net.sf.basedb.core.ItemContext"
     37  import="net.sf.basedb.core.Nameable"
    3738  import="net.sf.basedb.core.Permission"
    3839  import="net.sf.basedb.core.PluginDefinition"
     
    4647  import="net.sf.basedb.core.plugin.Plugin"
    4748  import="net.sf.basedb.util.Enumeration"
     49  import="net.sf.basedb.util.ShareableUtil"
    4850  import="net.sf.basedb.clients.web.Base"
    4951  import="net.sf.basedb.clients.web.PermissionUtil"
     
    5153  import="net.sf.basedb.clients.web.util.HTML"
    5254  import="net.sf.basedb.util.Values"
     55  import="java.util.Iterator"
    5356  import="java.util.List"
    5457  import="java.util.Map"
     
    296299        id="permission"
    297300        title="Permission"
     301      />
     302      <tbl:columndef
     303        id="sharedTo"
     304        title="Shared to"
    298305      />
    299306      <tbl:toolbar
     
    559566                <tbl:cell column="description"><%=HTML.encodeTags(item.getDescription())%></tbl:cell>
    560567                <tbl:cell column="permission"><%=PermissionUtil.getShortPermissions(item)%></tbl:cell>
     568                <tbl:cell column="sharedTo">
     569                  <%
     570                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     571                  while(sharees.hasNext())
     572                  {
     573                    Nameable n = sharees.next();
     574                    if (mode.hasPropertyLink())
     575                    {
     576                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     577                    }
     578                    else
     579                    {
     580                      out.write(HTML.encodeTags(n.getName()));
     581                    }
     582                    out.write(sharees.hasNext() ? ", " : "");
     583                  }
     584                  %>
     585                </tbl:cell>
    561586              </tbl:row>
    562587              <%
  • branches/webservices/www/admin/jobagents/view_agent.jsp

    r2978 r3581  
    4141  import="net.sf.basedb.core.ItemQuery"
    4242  import="net.sf.basedb.core.ItemResultList"
     43  import="net.sf.basedb.core.ItemResultIterator"
     44  import="net.sf.basedb.core.MultiPermissions"
     45  import="net.sf.basedb.core.Group"
     46  import="net.sf.basedb.core.Project"
    4347  import="net.sf.basedb.core.query.Orders"
    4448  import="net.sf.basedb.core.query.Hql"
     
    5559  import="java.util.Set"
    5660  import="java.util.Date"
     61  import="java.util.Collections"
    5762%>
    5863<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
     
    492497        <%
    493498      }
     499     
     500      // Tables with users/groups/projects that this item is shared to
     501      MultiPermissions mp = new MultiPermissions(Collections.singleton(agent));
     502      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     503      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     504      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     505     
     506      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     507      {
     508        %>
     509        <h4 class="docked">Shared to</h4>
     510        <tbl:table
     511          id="itemsSharedTo"
     512          clazz="itemlist"
     513          columns="all"
     514        >
     515          <tbl:columndef
     516            id="itemType"
     517            title="Item type"
     518          />
     519          <tbl:columndef
     520            id="name"
     521            title="Name"
     522          />
     523          <tbl:columndef
     524            id="permissions"
     525            title="Permissions"
     526          />
     527          <tbl:data>
     528            <tbl:columns>
     529            </tbl:columns>
     530            <tbl:rows>
     531            <%
     532            while(projects.hasNext())
     533            {
     534              Project project = projects.next();
     535              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     536              %>     
     537              <tbl:row>
     538                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     539                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     540                <tbl:cell column="permissions">
     541                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     542                </tbl:cell>
     543              </tbl:row>
     544              <%
     545            }
     546            while(groups.hasNext())
     547            {
     548              Group group = groups.next();
     549              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     550              %>
     551              <tbl:row>             
     552                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     553                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     554                <tbl:cell column="permissions">
     555                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     556                </tbl:cell>
     557              </tbl:row>
     558              <% 
     559            }
     560            while (users.hasNext())
     561            {
     562              User user = users.next();
     563              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     564              %>
     565              <tbl:row>             
     566                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     567                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     568                <tbl:cell column="permissions">
     569                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     570                </tbl:cell>
     571              </tbl:row>
     572              <%
     573            }
     574            %>
     575            </tbl:rows>
     576          </tbl:data>
     577        </tbl:table>
     578        <%
     579      }
     580      else
     581      {
     582        %>
     583        <h4>Shared to</h4>
     584        This job agent is not shared
     585        (or, you don't have permission to view the ones it is shared to).
     586        <%
     587      }     
    494588      %>     
    495589     
  • branches/webservices/www/admin/pluginconfigurations/list_configurations.jsp

    r3533 r3581  
    3535  import="net.sf.basedb.core.ItemResultList"
    3636  import="net.sf.basedb.core.ItemContext"
     37  import="net.sf.basedb.core.Nameable"
    3738  import="net.sf.basedb.core.Permission"
    3839  import="net.sf.basedb.core.PluginDefinition"
     
    4445  import="net.sf.basedb.util.Enumeration"
    4546  import="net.sf.basedb.util.JarClassLoader"
     47  import="net.sf.basedb.util.ShareableUtil"
    4648  import="net.sf.basedb.util.ToStringComparator"
    4749  import="net.sf.basedb.clients.web.Base"
     
    5153  import="net.sf.basedb.util.Values"
    5254  import="net.sf.basedb.clients.web.util.NameablePluginAdaptor"
     55  import="java.util.Iterator"
    5356  import="java.util.List"
    5457  import="java.util.Map"
     
    309312        id="permission"
    310313        title="Permission"
     314      />
     315      <tbl:columndef
     316        id="sharedTo"
     317        title="Shared to"
    311318      />
    312319      <tbl:toolbar
     
    511518                </tbl:cell>
    512519                <tbl:cell column="permission"><%=PermissionUtil.getShortPermissions(item)%></tbl:cell>
     520                <tbl:cell column="sharedTo">
     521                  <%
     522                  Iterator<Nameable> sharees = ShareableUtil.getSharedTo(dc, item).iterator();
     523                  while(sharees.hasNext())
     524                  {
     525                    Nameable n = sharees.next();
     526                    if (mode.hasPropertyLink())
     527                    {
     528                      out.write(Base.getLinkedName(ID, n, false, mode.hasEditLink()));
     529                    }
     530                    else
     531                    {
     532                      out.write(HTML.encodeTags(n.getName()));
     533                    }
     534                    out.write(sharees.hasNext() ? ", " : "");
     535                  }
     536                  %>
     537                </tbl:cell>
    513538              </tbl:row>
    514539              <%
  • branches/webservices/www/admin/pluginconfigurations/view_configuration.jsp

    r2978 r3581  
    2929  import="net.sf.basedb.core.DbControl"
    3030  import="net.sf.basedb.core.SystemItems"
     31  import="net.sf.basedb.core.Group"
    3132  import="net.sf.basedb.core.Item"
    3233  import="net.sf.basedb.core.ItemContext"
     34  import="net.sf.basedb.core.ItemResultIterator"
    3335  import="net.sf.basedb.core.Permission"
    3436  import="net.sf.basedb.core.PluginDefinition"
     
    3840  import="net.sf.basedb.core.BasicItem"
    3941  import="net.sf.basedb.core.File"
     42  import="net.sf.basedb.core.MultiPermissions"
    4043  import="net.sf.basedb.core.Nameable"
    4144  import="net.sf.basedb.core.PermissionDeniedException"
     
    4346  import="net.sf.basedb.core.plugin.GuiContext"
    4447  import="net.sf.basedb.core.plugin.Plugin"
     48  import="net.sf.basedb.core.Project"
    4549  import="net.sf.basedb.util.JarClassLoader"
    4650  import="net.sf.basedb.util.ToStringComparator"
     
    107111
    108112  <base:page title="<%=title%>">
    109   <base:head scripts="tabcontrol.js" styles="toolbar.css,headertabcontrol.css,path.css">
     113  <base:head scripts="table.js,tabcontrol.js" styles="table.css,toolbar.css,headertabcontrol.css,path.css">
    110114    <script language="JavaScript">
    111115    function editItem()
     
    247251            visible="<%=configuration.isRemoved()%>"> This item has been flagged for deletion<br></base:icon>
    248252          <base:icon image="shared.gif"
    249             visible="<%=configuration.isShared()%>"> This item is shared to other user, groups and/or projects</base:icon>
     253            visible="<%=configuration.isShared()%>"> This item is shared to other users, groups and/or projects</base:icon>
    250254        </div>
    251255        <%
    252256      }
    253257      %>
    254       <table class="form" cellspacing=0>
     258      <table class="form" cellspacing="0">
    255259      <tr>
    256260        <td class="prompt">Name</td>
     
    276280      </tr>
    277281      </table>
     282   
     283      <%   
     284      // Tables with users/groups/projects that this item is shared to
     285      MultiPermissions mp = new MultiPermissions(Collections.singleton(configuration));
     286      ItemResultIterator<User> users = mp.getUsers().iterate(dc);
     287      ItemResultIterator<Group> groups = mp.getGroups().iterate(dc);
     288      ItemResultIterator<Project> projects = mp.getProjects().iterate(dc);
     289     
     290      if (users.hasNext() || groups.hasNext() || projects.hasNext())
     291      {
     292        %>
     293        <h4 class="docked">Shared to</h4>
     294        <tbl:table
     295          id="itemsSharedTo"
     296          clazz="itemlist"
     297          columns="all"
     298        >
     299          <tbl:columndef
     300            id="itemType"
     301            title="Item type"
     302          />
     303          <tbl:columndef
     304            id="name"
     305            title="Name"
     306          />
     307          <tbl:columndef
     308            id="permissions"
     309            title="Permissions"
     310          />
     311          <tbl:data>
     312            <tbl:columns>
     313            </tbl:columns>
     314            <tbl:rows>
     315            <%
     316            while(projects.hasNext())
     317            {
     318              Project project = projects.next();
     319              Set<Permission> permissions = mp.getPermissions(project).values().iterator().next();
     320              %>     
     321              <tbl:row>
     322                <tbl:cell column="itemType"><%=project.getType()%></tbl:cell>
     323                <tbl:cell column="name"><%=Base.getLinkedName(ID, project, false, true)%></tbl:cell>
     324                <tbl:cell column="permissions">
     325                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     326                </tbl:cell>
     327              </tbl:row>
     328              <%
     329            }
     330            while(groups.hasNext())
     331            {
     332              Group group = groups.next();
     333              Set<Permission> permissions = mp.getPermissions(group).values().iterator().next();
     334              %>
     335              <tbl:row>             
     336                <tbl:cell column="itemType"><%=group.getType()%></tbl:cell>
     337                <tbl:cell column="name"><%=Base.getLinkedName(ID, group, false, true)%></tbl:cell>
     338                <tbl:cell column="permissions">
     339                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     340                </tbl:cell>
     341              </tbl:row>
     342              <% 
     343            }
     344            while (users.hasNext())
     345            {
     346              User user = users.next();
     347              Set<Permission> permissions = mp.getPermissions(user).values().iterator().next();
     348              %>
     349              <tbl:row>             
     350                <tbl:cell column="itemType"><%=user.getType()%></tbl:cell>
     351                <tbl:cell column="name"><%=Base.getLinkedName(ID, user, false, true)%></tbl:cell>
     352                <tbl:cell column="permissions">
     353                  <%=PermissionUtil.translatePermissionsToString(permissions)%>
     354                </tbl:cell>
     355              </tbl:row>
     356              <%
     357            }
     358            %>
     359            </tbl:rows>
     360          </tbl:data>
     361        </tbl:table>
     362        <%
     363      }
     364      else
     365      {
     366        %>
     367        <h4>Shared to</h4>
     368        This configuration is not shared
     369        (or, you don't have permission to view the ones it is shared to).
     370        <%
     371      }
     372      %>
    278373    </div>
    279374
     
    282377      <t:tab id="parameters" title="Configuration parameters" >
    283378      <div class="boxed">
    284       <table class="form" cellspacing=0>
     379      <table class="form" cellspacing="0">
    285380      <%
    286381      if (plugin != null)
  • branches/webservices/www/admin/plugindefinitions/list_plugins.jsp

    r3533 r3581  
    3737  import="net.sf.basedb.core.ItemResultList"
    3838  import="net.sf.basedb.core.ItemContext"
     39  import="net.sf.basedb.core.Nameable"
    3940  import="net.sf.basedb.core.Permission"
    4041  import="net.sf.basedb.core.PluginDefinition"
     
    4748  import="net.sf.basedb.util.Enumeration"
    4849  import="net.sf.basedb.util.JarClassLoader"
     50  import="net.sf.basedb.util.ShareableUtil"
    4951  import="net.sf.basedb.util.ToStringComparator"
    5052  import="net.sf.basedb.clients.web.Base"