source: trunk/doc/src/docbook/developer/core_ref.xml @ 5780

Last change on this file since 5780 was 5780, checked in by Nicklas Nordborg, 10 years ago

References #1590: Documentation cleanup

Updated developer documentation "API overview". The chapter has been renamed to "The BASE API" and I intend to merge some information from the "Core developer reference" with this chapter.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 133.3 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE chapter PUBLIC
3    "-//Dawid Weiss//DTD DocBook V3.1-Based Extension for XML and graphics inclusion//EN"
4    "../../../../lib/docbook/preprocess/dweiss-docbook-extensions.dtd">
5<!--
6  $Id: core_ref.xml 5780 2011-10-04 11:01:20Z nicklas $
7
8  Copyright (C) 2007 Peter Johansson, Nicklas Nordborg, Martin Svensson
9
10  This file is part of BASE - BioArray Software Environment.
11  Available at http://base.thep.lu.se/
12
13  BASE is free software; you can redistribute it and/or
14  modify it under the terms of the GNU General Public License
15  as published by the Free Software Foundation; either version 3
16  of the License, or (at your option) any later version.
17
18  BASE is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22
23  You should have received a copy of the GNU General Public License
24  along with BASE. If not, see <http://www.gnu.org/licenses/>.
25-->
26
27<chapter id="core_ref">
28  <title>Core developer reference</title>
29
30  <sect1 id="core_ref.release">
31    <title>Publishing a new release</title>
32    <para>
33      This documentation is available on the <ulink url="http://base.thep.lu.se/wiki/ReleaseProcedure">BASE wiki</ulink>.
34    </para>
35  </sect1>
36 
37  <sect1 id="core_ref.build">
38    <title>Subversion / building BASE</title>
39    <para>
40      This documentation is available on the <ulink url="http://base.thep.lu.se/wiki/BuildingBase">BASE wiki</ulink>.
41    </para>
42  </sect1>
43
44  <sect1 id="core_ref.rules" chunked="1">
45    <title>Coding rules and guidelines</title>
46   
47    <sect2 id="core_ref.rules.devprocess">
48      <title>Development process and other important procedures</title>
49      <para>
50         This section describes the development process we try to use in the BASE project.
51         It is not carved in stone and deviations may occur. For every new feature
52         or enhancement the procure below should be followed.
53         If you encounter any problems, arrange a group meeting. Someone else
54         may have the solution! The text is biased towards adding new
55         items to BASE, but it should be possible to use the general outline
56         even for other types of features.
57      </para>
58     
59      <bridgehead>1. Group meeting</bridgehead>
60      <itemizedlist>
61      <listitem>
62        <para>
63        The group should have a short meeting and discuss the new or changed
64        feature. Problem areas should be identified, not solved!
65        </para>
66      </listitem>
67      <listitem>
68        <para>
69        The person who is going to make the analysis, design and development is
70        responsible for taking notes. They should be kept until the analysis
71        and design phase has been finished.     
72        </para>
73      </listitem>
74      <listitem>
75        <para>
76        A follow-up meeting should be held at the end of the analysis phase. 
77        </para>
78      </listitem>
79      <listitem>
80        <para>
81        A single meeting may of course discuss more than one feature.
82        </para>
83      </listitem>
84      </itemizedlist>
85     
86      <bridgehead>2. Analysis and design</bridgehead>
87      <itemizedlist>
88      <listitem>
89        <para>
90        Create an diagram of the classes including their properties, links and associations.
91        Use the already existing diagrams and code as a template.
92        The diagram should have information about cache and proxy settings.
93        </para>
94      </listitem>
95      <listitem>
96        <para>
97        Write a short document about the diagram, especially things that are not obvious
98        and explain any deviations from the recommendations in the coding guidelines.
99        </para>
100      </listitem>
101      <listitem>
102        <para>
103        Identify things that may affect backwards compatibility. For more
104        information about such things read <xref linkend="base_api.public" />
105        and <xref linkend="core_ref.rules.compatibility" />.
106        </para>
107      </listitem>
108      <listitem>
109        <para>
110        Identify what parts of the documentation that needs to changed or added
111        to describe the new feature. This includes, but is not limited to:
112        <itemizedlist>
113        <listitem>
114          <para>
115          User and administrator documentation, how to use the feature, screenshots,
116          etc.
117          </para> 
118        </listitem>
119        <listitem>
120          <para>
121          Plug-in and core developer documentation, code examples, database schema changes,
122          etc.
123          </para> 
124        </listitem>
125        </itemizedlist>
126        </para>
127      </listitem>
128      <listitem>
129        <para>
130        If there are any problems with the existing code, these should be solved at
131        this stage. Write some prototype code for testing if necessary.
132        </para>
133      </listitem>
134      <listitem>
135        <para>
136        Group meeting to verify that the specified solution is ok, and to make sure
137        everybody has enough knowledge of the solution.
138        </para>
139      </listitem>
140      </itemizedlist>
141     
142      <bridgehead>3. Create the classes for the data layer</bridgehead>
143      <itemizedlist>
144      <listitem>
145        <para>
146        If step 2 is properly done, this should not take long.
147        </para>
148      </listitem>
149      <listitem>
150        <para>
151        Follow the coding guidelines in <xref linkend="core_ref.rules.datalayer" />.
152        </para>
153      </listitem>
154      <listitem>
155        <para>
156        At the end of this step, go back and have a lock at the diagram/documentation
157        from the analysis and design phase and make sure everything is still correct.
158        </para>
159      </listitem>
160      </itemizedlist>
161     
162      <bridgehead>4. Create the corresponding classes in the core layer</bridgehead>
163      <itemizedlist>
164      <listitem>
165        <para>
166        For simple cases this is also easy. Other cases may require more effort.
167        </para>
168      </listitem>
169      <listitem>
170        <para>
171        If needed, go back to the analysis and design phase and do some more investigations.
172        Make sure the documentation is updated if there are changes.
173        </para>
174      </listitem>
175      </itemizedlist>
176     
177      <bridgehead>5. Create test code</bridgehead>
178      <itemizedlist>
179      <listitem>
180        <para>
181        Build on and use the existing test as much as possible.
182        </para>
183      </listitem>
184      </itemizedlist>
185     
186      <bridgehead>6. Write code to update existing installations</bridgehead>
187      <important>
188      <itemizedlist>
189      <listitem>
190        <para>
191        If the database schema is changed or if there for some reason is need to update
192        existing data in the database, the <constant>Install.SCHEMA_VERSION</constant>
193        counter must be increased.
194        </para>
195      </listitem>
196      <listitem>
197        <para>
198        Add code to the <classname docapi="net.sf.basedb.core">net.sf.basedb.core.Update</classname> class
199        to increase the schema version and modify data in existing installations.
200        </para>
201      </listitem>
202      </itemizedlist>
203      </important>
204     
205      <bridgehead>7. Write new and update existing user documentation</bridgehead>
206      <itemizedlist>
207      <listitem>
208        <para>
209        Most likely, users and plug-in developers wants to know about the feature.
210        </para>
211      </listitem>
212      </itemizedlist>
213
214      <important>
215      <para>
216      Do not forget to update the <xref linkend="appendix.incompatible" /> document
217      if you have introduced any incomaptible changes.
218      </para>
219      </important>
220     
221    </sect2>
222    <sect2 id="core_ref.rules.style">
223      <title>General coding style guidelines</title>
224     
225      <sect3 id="core_ref.rules.naming">
226        <title>Naming</title>
227       
228        <variablelist>
229        <varlistentry>
230          <term>General</term>
231          <listitem>
232            <para>
233              All names should be in English. Names should be descriptive and derived from the the
234              domain the code is intended for. Try to avoid names longer than twenty characters.
235            </para>
236          </listitem>
237        </varlistentry>
238       
239        <varlistentry>
240          <term>Packages</term>
241          <listitem>
242            <para>
243              Package names must be in all lower case letters. The top-level package of
244              BASE is <code>net.sf.basedb</code>.
245            </para>
246          </listitem>
247        </varlistentry>
248       
249        <varlistentry>
250          <term>Classes and Interfaces</term>
251          <listitem>
252            <para>
253            Names of classes and interfaces should be a concatenation of one or more words.
254            The initial letter of all words in the name, including the first word, should be upper case
255            letters. The rest of the characters should be lower case. Example:
256            </para>
257            <programlisting language="java">
258public class SoftwareType
259{
260   ...
261}
262</programlisting>
263           
264          </listitem>
265        </varlistentry>
266       
267        <varlistentry>
268          <term>Constant member variables</term>
269          <listitem>
270            <para>
271            Constant member variables, usually defined <emphasis>static final</emphasis>, should be named
272            using all upper case characters. Words in the name should be separated by underscore characters.
273            Example:
274            </para>
275            <programlisting language="java">
276public static final int VERSION_NUMBER = 3;
277</programlisting>
278          </listitem>
279        </varlistentry>
280       
281        <varlistentry>
282          <term>Private member variables</term>
283          <listitem>
284            <para>
285            Private member variables should be a concatenation of one or more descriptive words.
286            The initial letter of all words in the name, except the first word, should be upper
287            case letters. The rest of the characters should be lower case. Example:
288            </para>
289            <programlisting language="java">
290private String loginComment;
291</programlisting>
292          </listitem>
293        </varlistentry>
294       
295        <varlistentry>
296          <term>Methods</term>
297          <listitem>
298            <para>
299            Methods should be named using a descriptive statement, usually made up by several words.
300            Typically the first word is a verb, stating the action and the others stating the target
301            and attributes. Lower and upper case letters should then be mixed, with all words in the
302            name except the first one starting with an upper case letter and the rest being in
303            lower case letters. Example:
304            </para>
305            <programlisting language="java">
306<![CDATA[
307public ItemQuery<Annotation> getAllInheritedAnnotations()
308{
309   ...
310}
311]]>
312</programlisting>
313          </listitem>
314        </varlistentry>
315       
316        <varlistentry>
317          <term>Mutator (get/set) methods</term>
318          <listitem>
319            <para>
320            Avoid direct access to attributes (member variables) from outside of a class.
321            Instead make attributes private and use mutator methods to access them. Prefix
322            the mutator methods with get and set respectively to fetch or change an attribute.
323            If the getter returns a boolean value prefix the mutator method with (typically)
324            is, has or can. Examples:
325            </para>
326            <programlisting language="java">
327private String name;
328public String getName()
329{
330   return name;
331}
332public void setName(String name)
333{
334  this.name = name;
335}
336
337private boolean activated;
338public boolean isActivated()
339{
340   return activated;
341}
342</programlisting>
343           
344          </listitem>
345        </varlistentry>
346
347        <varlistentry>
348          <term>Exceptions</term>
349          <listitem>
350            <para>
351            The names of Exceptions must end with the word <emphasis>Exception</emphasis>.
352            Example:
353            </para>
354            <programlisting language="java">
355public class NoMoreNumbersException
356   extends Exception
357{
358   ...
359}
360</programlisting>
361          </listitem>
362        </varlistentry>
363      </variablelist>
364     
365    </sect3>
366   
367    <sect3 id="core_ref.rules.layout">
368      <title>Layout and comments</title>
369   
370      <variablelist>
371        <varlistentry>
372          <term>Interface layout</term>
373          <listitem>
374            <para>
375            Interfaces should only have public members, i.e. static attributes and method prototypes.
376            </para>
377          </listitem>
378        </varlistentry>
379       
380        <varlistentry>
381          <term>White space</term>
382          <listitem>
383            <para>
384            All code must be properly indented. In general each new block starts a
385            new indentation level. Use <emphasis>tab</emphasis> when indenting.
386            </para>
387          </listitem>
388        </varlistentry>
389       
390        <varlistentry>
391          <term>Code blocks</term>
392          <listitem>
393            <para>
394            The starting brace "{" of a code block should be placed on a line by itself at
395            the same indentation level as the preceeding line of code. The first line in
396            the new block should be indented one tab-stop more. The ending brace "}"
397            should be placed at the same indentation level as the matching starting brace.
398            Use braces even if the code block is only one line. Example:
399            </para>
400            <programlisting language="java">
401public String getName()
402{
403   if (name == null)
404   {
405      return "unknown";
406   }
407   else
408   {
409      return name;
410   }
411}
412</programlisting>
413          </listitem>
414        </varlistentry>
415       
416        <varlistentry>
417          <term>Javadoc</term>
418          <listitem>
419            <para>
420            Packages, classes, public methods and public attributes should be commented in Javadoc style.
421            It is recommended that private and protected methods also has some comments, but maybe not
422            as detailed as the public ones.
423            </para>
424           
425            <itemizedlist>
426              <listitem>All comments should be in English.</listitem>
427              <listitem>Do not start each line of a comment with a star.</listitem>
428            </itemizedlist>
429           
430            <para>
431              More info about Javadoc can be found at: <ulink 
432                url="http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html"
433                >http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html</ulink>
434            </para>
435          </listitem>
436        </varlistentry>
437       
438        <varlistentry>
439          <term>Package comments</term>
440          <listitem>
441            <para>
442            Place package comments in a file named <filename>package.html</filename> in the
443            source code directory.
444            </para>
445          </listitem>
446        </varlistentry>
447       
448        <varlistentry>
449          <term>Class comments</term>
450          <listitem>
451            <para>
452            A class comment should start with a general description of the class and what it does.
453            Use the <code>@author</code> tag to specify the names of the programmers that was involved
454            in coding the file and the <code>@since</code> tag to specify the version of BASE when the
455            class first appeared. Example:
456            </para>
457            <programlisting language="java">
458/**
459   ...
460   @author Nicklas, Martin
461   @since 2.0
462*/
463public class BasicItem
464{
465  ...
466}
467</programlisting>
468          </listitem>
469        </varlistentry>
470       
471        <varlistentry>
472          <term>Method comments</term>
473          <listitem>
474            <para>
475            A method comment should start with a general description of the method and what it does.
476            Use <code>@param</code> to describe each parameter and <code>@return</code> to describe
477            what the method returns. Use <code>@throws</code> to describe all checked exceptions
478            including when and why they can be thrown. Use <code>@see</code> to link to other related
479            method and information.
480            </para>
481          </listitem>
482        </varlistentry>
483       
484        <varlistentry>
485          <term>Attribute comments</term>
486          <listitem>
487            <para>
488            If it is a static final attribute, describe what the attribute is for and where it is typically used.
489            </para>
490          </listitem>
491        </varlistentry>
492       
493        <varlistentry>
494          <term>@base.developer</term>
495          <listitem>
496            <para>
497            The <code>@base.developer</code> tag can be used anywhere to add comments that are
498            mainly targeted to the developers of BASE.
499            </para>
500          </listitem>
501        </varlistentry>
502
503        <varlistentry>
504          <term>@base.internal</term>
505          <listitem>
506            <para>
507            The <code>@base.internal</code> tag can be used at package and class-level
508            documentation to mark that part of the code as an internal API that should
509            not be used by plug-ins and other client code. See
510            <xref linkend="base_api.public" />.
511            </para>
512          </listitem>
513        </varlistentry>
514       
515        <varlistentry>
516          <term>Inline comments</term>
517          <listitem>
518            <itemizedlist>
519              <listitem>All comments should be in English.</listitem>
520              <listitem>
521                Comment on why instead of what. Your code should be
522                clear enough to answer questions on what it does. It is more
523                important to document why it does it.
524              </listitem>
525              <listitem>Do not place end line comments at the end of statements.</listitem>
526              <listitem>
527                Do not use decorated banner like comments, as these are hard to maintain.
528                If more extensive commenting is needed - use Javadoc.
529              </listitem>
530              <listitem>
531                Avoid using semicolon (;) as part of inline comments. Searching for all
532                comments containing a semicolon is used to find commented out code blocks.
533              </listitem>
534            </itemizedlist>
535         
536          </listitem>
537        </varlistentry>
538       
539        <varlistentry>
540          <term>Commented out code</term>
541          <listitem>
542            <para>
543            Avoid leaving code that is commented out. It is a distraction when
544            maintaining the code. Sometimes, for example during a big refactoring,
545            it is not possible to fix everything at once. In this case it is allowed
546            to comment out code, but it is recommended that a <emphasis>TODO</emphasis>
547            marker (see below) is added to make it easier to find places that
548            need to be fixed later.
549            </para>
550          </listitem>
551        </varlistentry>
552       
553        <varlistentry>
554          <term>Todo comments</term>
555          <listitem>
556            <para>
557            If there are parts of the code that cannot be completed at the time the majority of the code
558            is written, place a comment starting with TODO (in capital letters), followed with a
559            description of what needs to be done. If there is a ticket in the Trac server, use the
560            ticket number in the comment. Example:
561            </para>
562            <programlisting language="java">
563public static Date copy(Date value)
564{
565   return value == null ? null : new Date(value.getTime());
566   // TODO (#1234): check if there is a better way to copy
567}
568</programlisting>
569          </listitem>
570        </varlistentry>
571       
572        <varlistentry>
573          <term>Subversion comment and GNU licence message</term>
574          <listitem>
575            <para>
576            Each file should start with a subversion comment and the GNU licence and copyright message.
577            Non-java files should also include this information, in a format appropriate for the
578            specific file.
579            </para>
580            <programlisting language="java">
581<![CDATA[
582/*
583   $Id: core_ref.xml 5780 2011-10-04 11:01:20Z nicklas $
584
585   Copyright (C) Authors contributing to this file.
586
587   This file is part of BASE - BioArray Software Environment.
588   Available at http://base.thep.lu.se/
589
590   BASE is free software; you can redistribute it and/or
591   modify it under the terms of the GNU General Public License
592   as published by the Free Software Foundation; either version 3
593   of the License, or (at your option) any later version.
594
595   BASE is distributed in the hope that it will be useful,
596   but WITHOUT ANY WARRANTY; without even the implied warranty of
597   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
598   GNU General Public License for more details.
599
600   You should have received a copy of the GNU General Public License
601   along with BASE. If not, see <http://www.gnu.org/licenses/>.
602*/
603]]>
604</programlisting>
605          </listitem>
606        </varlistentry>
607        </variablelist>
608       
609      </sect3>
610
611    <sect3 id="core_ref.rules.statements">
612      <title>Statements</title>
613
614        <variablelist>       
615        <varlistentry>
616          <term>Package and import statements</term>
617          <listitem>
618            <para>
619            The package statement is the first statement to appear in the source file. All declared classes
620            must belong to a named package. It is not allowed for classes to belong to the "default" package,
621            i.e. to omit the package statement in the source file. Exception: Test code may belong to the
622            default package.
623            </para>
624           
625            <para>
626            Import statements should follow directly after the package statement. Try to avoid
627            preceeding class names in code with package names. Instead use import statements.
628            </para>
629           
630            <para>
631            Wildcards in import statements make it difficult to see dependencies,
632            other than those to packages. Therefore import classes/interfaces explicitely.
633            The only exception is when classes in subpackages to the current package are accessed.
634            Such items are either imported explicitely or the whole subpackage may be imported with
635            wildcard. However, avoid wildcard imports when subpackages are large - more than approximately
636            4 items.
637            </para>
638           
639            <para>
640            Do not explicitely import packages or classes not used in your program code.
641            Try to maintain an alphabetical order among the imported classes. Group
642            classes from the same package. Most IDE:s have functionality for maintaining
643            import statements. Use it.
644            </para>
645           
646          </listitem>
647        </varlistentry>
648       
649        <varlistentry>
650          <term>Inside a class, attributes and methods should be organised in the following order:</term>
651          <listitem>
652            <itemizedlist>
653              <listitem>public static final attributes</listitem>
654              <listitem>other static attributes</listitem>
655              <listitem>public static methods</listitem>
656              <listitem>other static methods</listitem>
657              <listitem>private attributes</listitem>
658              <listitem>constructors</listitem>
659              <listitem>Methods defined by interfaces, grouped by the interface in which they are defined</listitem>
660              <listitem>Methods that override a method from a superclass, with methods from the topmost superclass first</listitem>
661              <listitem>Additional methods for the specific class</listitem>
662            </itemizedlist>
663          </listitem>
664        </varlistentry>
665       
666        <varlistentry>
667          <term>Classes and interfaces</term>
668          <listitem>
669            <para>
670            Class and interface statements should be organized in the following manner:
671            </para>
672           
673            <itemizedlist>
674              <listitem>class or interface statement</listitem>
675              <listitem>extends statement indented on a separate row</listitem>
676              <listitem>implements statement indented on one or more rows</listitem>
677              <listitem>class body</listitem>
678            </itemizedlist>
679            <programlisting language="java">
680public class SomeClass
681   extends SomeBase
682   implements Clonable, SomeInterface
683{
684   ...
685}
686
687public interface Testable
688   extends Clonable
689{
690   ...
691}
692</programlisting>
693
694          </listitem>
695        </varlistentry>
696       
697        <varlistentry>
698          <term>Methods</term>
699          <listitem>
700            <para>
701            If a method throws checked exceptions, these should be declared indented on a separate row directly
702            after the method declaration. Example:
703            </para>
704            <programlisting language="java">
705public int getNextValue(int previousValue)
706   throws NoMoreValuesException
707{
708   ...
709}
710</programlisting>
711          </listitem>
712        </varlistentry>
713       
714        <varlistentry>
715          <term>Local variables</term>
716          <listitem>
717            <para>
718            Local variables should be declared and initialized where they are used.
719            They should be declared in the smallest possible scope. Avoid overloading
720            variable names in inner blocks.
721            </para>
722          </listitem>
723        </varlistentry>
724       
725        <varlistentry>
726          <term>Array declarations</term>
727          <listitem>
728            <para>
729            The square brackets indicating an array of something should be immediately to
730            the right of whatever class or datatype the array consists of
731            (e.g. <code>String[] args</code>) do not use C-style array declarations
732            (<code>String args[]</code>).
733            </para>
734          </listitem>
735        </varlistentry>
736       
737        <varlistentry>
738          <term>Conditional statements</term>
739          <listitem>
740            <itemizedlist>
741              <listitem>
742              There must always be braces around the block following the condition control structure, even if it's
743              just a single statement block. This doesn't apply to the cases when the single statement is on
744              the same line as the condition.
745              </listitem>
746              <listitem>Avoid placing statements resulting in side effects (e.g. function calls) in the condition construct.</listitem>
747              <listitem>Do not jump out of conditional blocks with break, return or exit. The exception is the usage of break in switch-statements.</listitem>
748              <listitem>Use continue-statements in for- and while- loops with caution. It's recommended to mark the statement with a clear comment.</listitem>
749            </itemizedlist>
750           
751            <programlisting language="java">
752// IF-statements:
753if (...)
754{
755   ...
756}
757else
758{
759   ...
760}
761
762if (...) ...;
763
764
765// FOR-statements:
766for (init; condition; update)
767{
768   ...
769   /* #### CONTINUE-STATEMENT #### */
770   if (...) continue;
771   ...
772}
773
774// WHILE-statement:
775while (condition)
776{
777   ...
778}
779
780// DO-WHILE-statement:
781do
782{
783   ...
784}
785while (condition);
786
787// SWITCH-statement:
788switch (operand)
789{
790   case: ...
791   {
792      ...
793      break;
794   }
795   default:
796   {
797      ...
798   }
799}
800
801
802// Exception blocks:
803try
804{
805   ...
806}
807catch (SpecialException se)
808{
809   ...
810}
811catch (Exception e)
812{
813   ...
814}
815finally
816{
817   ...
818}
819</programlisting>
820          </listitem>
821        </varlistentry>     
822        </variablelist>       
823      </sect3>
824
825    </sect2>
826 
827    <sect2 id="core_ref.rules.compatibility">
828      <title>API changes and backwards compatibility</title>
829      <para>
830        The main rule is to do not introduce any changes that are
831        backwards incompatible. That is, existing client applications
832        and plug-ins should continue to run in the next release of BASE,
833        without the need to change them. It may sound easy but there are
834        many things to watch out for. There is a great article about this subject on <ulink 
835        url="http://wiki.eclipse.org/index.php/Evolving_Java-based_APIs"
836          >http://wiki.eclipse.org/index.php/Evolving_Java-based_APIs</ulink>.
837      </para>
838     
839     
840      <variablelist>
841        <varlistentry>
842          <term>The Public API</term>
843          <listitem>
844            <para>
845            Not all code in BASE is considered to be part of the public
846            API. See <xref linkend="base_api.public" /> and
847            <ulink url="../../../api/index.html">the javadoc</ulink> 
848            for information about the public API. Changes made to
849            the internal API does not have to follow the same rules.
850            </para>
851          </listitem>
852        </varlistentry>
853       
854        <varlistentry>
855          <term>Binary compatibility</term>
856          <listitem>
857            <para>
858            This is hardest requirement and means that existing binaries must run
859            with the updated BASE version. The Eclipse document discusses this
860            type of compatibility in great detail.
861            </para>
862          </listitem>
863        </varlistentry>
864
865        <varlistentry>
866          <term>Contract compatibility</term>
867          <listitem>
868            <para>
869            Methods should continue to do things in the same ways as before. Avoid
870            introducing side-effects and expanding/contracting the allowed range
871            of return or parameter values. This may not always be easy to keep this
872            type of compatibility. For example, adding a new option to an enumeration
873            may break code that is not prepared for it.
874            </para>
875          </listitem>
876        </varlistentry>
877
878        <varlistentry>
879          <term>Internal data structure compatibility</term>
880          <listitem>
881            <para>
882            It may not be possible to keep the internal data structures. If they change the
883            update script should convert the old data to the new format. Avoid exposing
884            the internal data structure to client applications. Use wrapper classes, etc,
885            to hide as much as possible.
886            </para>
887          </listitem>
888        </varlistentry>
889
890        <varlistentry>
891          <term>Source code compatibility</term>
892          <listitem>
893            <para>
894            This is not an important issue and in most cases the problems are easy to fix.
895            </para>
896          </listitem>
897        </varlistentry>
898     
899      </variablelist>
900     
901      <important>
902        <title>Do not forget to log changes!</title>
903        <para>
904        Any change that may affect backwards compatibility must be logged in
905        <xref linkend="appendix.incompatible" />.
906        </para>
907      </important>
908 
909    </sect2>
910   
911    <sect2 id="core_ref.rules.datalayer">
912      <title>Data-layer rules</title>
913
914      <para>
915        The coding guidelines for this package has been slightly modified from the
916        the general coding guidelines. Here is a short list with the changes.
917      </para>
918     
919      <variablelist>
920        <varlistentry>
921          <term>Class and interface names</term>
922          <listitem>
923            <para>
924              Class names should follow the general guidelines, but should in most
925              cases end with <classname>Data</classname>.
926            </para>
927            <programlisting language="java">
928public class SampleData
929   extends CommonData
930   implements DiskConsumableData
931{
932   ...
933}
934</programlisting>
935          </listitem>
936        </varlistentry>
937
938        <varlistentry>
939          <term>Attributes and methods order</term>
940          <listitem>
941            <para>
942              Inside a class, attributes and methods should be organised in related groups,
943              ie. the private attribute is together with the getter and setter methods that uses
944              that attribute. This makes it easy to re-use existing code with copy-and-paste
945              operations.
946            </para>
947            <programlisting language="java">
948public static int long MAX_ADDRESS_LENGTH = 255;
949private String address;
950/**
951   @hibernate.property column="`address`" type="string" length="255" not-null="false"
952*/
953public String getAddress()
954{
955   return address;
956}
957public void setAddress(String address)
958{
959   this.address = address;
960}
961
962private int row;
963/**
964   @hibernate.property column="`row`" type="int"
965*/
966public int getRow()
967{
968   return row;
969}
970public void setRow(int row)
971{
972   this.row = row;
973}       
974</programlisting>
975          </listitem>
976        </varlistentry>
977
978        <varlistentry>
979          <term>Extend/implement the basic classes and interfaces</term>
980          <listitem>
981            <para>
982            Each data-class must inherit from one of the already existing abstract base classes.
983            They contain code that is common to all classes, for example implementations of
984            the <methodname>equals()</methodname> and <methodname>hashCode()</methodname>
985            methods or how to link with the owner of an item. For information about
986            which classes/interfaces that can be used see <xref linkend="data_api.basic" />.
987            </para>
988          </listitem>
989        </varlistentry>
990
991        <varlistentry>
992          <term>Define a public no-argument constructor</term>
993          <listitem>
994            <para>
995            Always define a public no-argument constructor. No other constructors are needed.
996            If we want to use other persistence mechanisms or serializability in the future
997            this type of constructor is probably the most compatible. The constructor should
998            be empty and not contain any code. Do not initialise properties or create new objects
999            for internal use. Most of the time the object is loaded by
1000            Hibernate and Hibernate will ensure that it is properly initialised by calling
1001            all setter methods.
1002            </para>
1003            <para>
1004              For example, a many-to-many relation usually has a <interfacename>Set</interfacename>
1005              or a <interfacename>Map</interfacename> to hold the links to the other objects. Do not
1006              create a new <classname>HashSet</classname> or <classname>HashMap</classname>
1007              in the constructor. Wait until the getter method is called and only create a new
1008              object if Hibernate hasn't already called the setter method with it's own object.
1009              See the code example below. There is also more information about this in
1010              <xref linkend="core_ref.rules.datalayer.manytomany" />.
1011            </para>
1012            <programlisting language="java">
1013<![CDATA[
1014// From GroupData.java
1015public GroupData()
1016{}
1017
1018private Set<UserData> users;
1019public Set<UserData> getUsers()
1020{
1021   if (users == null) users = new HashSet<UserData>();
1022   return users;
1023}
1024]]>
1025</programlisting>
1026
1027            <para>
1028            See also:
1029            </para>
1030           
1031            <itemizedlist>
1032            <listitem>
1033              <para>
1034              "Hibernate in action", chapter 3.2.3 "Writing POJOs", page 67-69
1035              </para>
1036            </listitem>
1037            <listitem>
1038              <para>
1039              Hibernate reference documentation: <ulink 
1040                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/persistent-classes.html#persistent-classes-pojo-constructor">4.1.1.
1041                Implement a no-argument constructor</ulink>
1042              </para>
1043            </listitem>
1044            </itemizedlist>
1045
1046          </listitem>
1047        </varlistentry>
1048
1049        <varlistentry>
1050          <term>Object identity</term>
1051          <listitem>
1052            <para>
1053              We use database identity to compare objects, ie. two objects are considered
1054              equal if they are of the same class and have the same id, thus representing the
1055              same database row. All this stuff is implemented by the <classname 
1056              docapi="net.sf.basedb.core.data">BasicData</classname> class. Therefore
1057              it is required that all classes are subclasses of this class. It is recommended
1058              that the <methodname>equals()</methodname> or <methodname>hashCode()</methodname>
1059              methods are not overridden by any of the subclasses. We would have liked to make
1060              them final, but then the proxy feature of Hibernate would not work.
1061            </para>
1062           
1063            <warning>
1064              <title>Avoid mixing saved and unsaved objects</title>
1065              <para>
1066                The approch used for object identity may give us a problem if we mix objects
1067                which hasn't been saved to the database, with objects loaded from the database.
1068                Our recommendation is to avoid that, and save any objects to the database before
1069                adding them to sets, maps or any other structure that uses the
1070                <methodname>equals()</methodname> and <methodname>hashCode()</methodname> methods.
1071              </para>
1072              <para>
1073                To be more specific, the problem arises because the following two rules for
1074                hash codes are contradicting when the hash code is based on the database id:
1075              </para>
1076              <orderedlist>
1077              <listitem>
1078                <para>
1079                The hash code of an object mustn't change.
1080                </para>
1081              </listitem>
1082              <listitem>
1083                <para>
1084                Equal objects must have equal hash code.
1085                </para>
1086              </listitem>
1087              </orderedlist>
1088              <para>
1089                For objects in the database, the hash code is based on the id. For new objects,
1090                which doesn't have an id yet, we fall back to the system hash code. But, what
1091                happens when we save the new object to the database? If nobody has asked for
1092                the hash code it is safe to use the id, otherwise we must stick with the system
1093                hash code. Now, imagine that we load the same object from the database in
1094                another Hibernate session. What will now happen? The loaded object will have
1095                it's hash code based on the id but the original object is still using the
1096                system hash code, which most likely is not the same as the id. Yet, the
1097                <methodname>equals()</methodname> method returns true. This is a violation
1098                of the contract for the equals method. If these two objects are used in a set
1099                it may cause unexpected behaviour. Therefore, do not put new objects in a
1100                set, or other collection, that calls the <methodname>hashCode()</methodname> 
1101                method before the object is saved to the database.         
1102              </para>
1103            </warning>
1104           
1105            <para>
1106            See also:
1107            </para>
1108            <itemizedlist>
1109            <listitem>
1110              <para>
1111              "Hibernate in action", chapter 3.4 "Understanding object identity", page 87-90
1112              </para>
1113            </listitem>
1114            <listitem>
1115              <para>
1116              "Hibernate in action", chapter 4.1.4 "The scope of object identity", page 119-121
1117              </para>
1118            </listitem>
1119            <listitem>
1120              <para>
1121              "Hibernate in action", chapter 4.1.6 "Implementing equals() and hashCode(), page 122-126
1122              </para>
1123            </listitem>
1124            <listitem>
1125              <para>
1126              Hibernate reference documentation: <ulink 
1127                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/persistent-classes.html#persistent-classes-equalshashcode">4.3. Implementing equals() and hashCode()</ulink>
1128              </para>
1129            </listitem>
1130            </itemizedlist>
1131
1132          </listitem>
1133        </varlistentry>
1134       
1135        <varlistentry>
1136          <term>No final methods</term>
1137          <listitem>
1138            <para>
1139              No methods should be tagged with the <code>final</code> keyword. This is a
1140              requirement to be able to use the proxy feature of Hibernate, which we need for
1141              performance reasons.
1142            </para>
1143   
1144            <para>
1145            See also:
1146            </para>
1147            <itemizedlist>
1148            <listitem>
1149              <para>
1150              Hibernate reference documentation: <ulink 
1151                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/persistent-classes.html#persistent-classes-pojo-final">4.1.3. Prefer non-final classes</ulink>
1152              </para>
1153            </listitem>
1154            <listitem>
1155              <para>
1156              Hibernate reference documentation: <ulink 
1157                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/performance.html#performance-fetching-proxies">21.1.3. Single-ended association proxies</ulink>
1158              </para>
1159            </listitem>
1160            </itemizedlist>
1161          </listitem>
1162        </varlistentry>
1163
1164
1165        <varlistentry>
1166          <term>Second-level cache</term>
1167          <listitem>
1168            <para>
1169              To gain performance we use the second-level cache of Hibernate. It is a transparent
1170              feature that doesn't affect the code in any way. The second-level cache is configured
1171              in the <filename>hibernate.cfg.xml</filename> and <filename>ehcache.xml</filename> 
1172              configuration files and not in the individual class mapping files. BASE is shipped
1173              with a standard configuration, but different deployment scenarios may have to fine-tune the cache
1174              settings for that particular hardware/software setup. It is beyond the scope of
1175              this document to discuss this issue.
1176            </para>
1177            <para>
1178              The second-level cache is suitable for objects that are rarely modified but
1179              are often needed. For example, we do not expect the user information represented
1180              by the <classname docapi="net.sf.basedb.core.data">UserData</classname> object to
1181              change very often, but it is displayed all the time as the owner of various items.
1182              Before coming up with a good caching strategy we have to answer the following questions:
1183            </para>
1184           
1185            <orderedlist>
1186            <listitem>
1187              <para>
1188              Should objects of this class be cached at all?
1189              </para>
1190            </listitem>
1191            <listitem>
1192              <para>
1193              How long timeout should we use?
1194              </para>
1195            </listitem>
1196            <listitem>
1197              <para>
1198              How many objects should we keep in memory or on disk?
1199              </para>
1200            </listitem>
1201            </orderedlist>
1202
1203            <para>
1204              The first question is the most important. Good candidates are classes with few
1205              objects that change rarely, but are read often. Also, objects which are linked
1206              to by many other objects are good candidates. The <classname docapi="net.sf.basedb.core.data">UserData</classname>
1207              class is an example which matches all three requirements. The <classname docapi="net.sf.basedb.core.data">TagData</classname>
1208              class is an example which fulfils the first two. The <classname docapi="net.sf.basedb.core.data">BioMaterialEventData</classname>
1209              class is on the other hand a bad cache candidate, since it is not linked to any
1210              other object than a <classname docapi="net.sf.basedb.core.data">BioMaterialData</classname> object.
1211            </para>
1212            <para>
1213              The answer to the second question depends on how often an object is modified.
1214              For most objects this time is probably several days or months, but we would
1215              not gain much by keeping objects in the cache for so long. Suddenly, the
1216              information has changed and we won't risk that old information is kept that
1217              long. We have set the timeout to 1 hour for all classes so far, and we don't
1218              recommend a longer timeout. The only exception is for immutable objects, that
1219              cannot be changed at all, which may have an infinite timeout.
1220            </para>
1221            <para>
1222              The answer to the third question depends a lot on the hardware (available memory).
1223              With lots of memory we can afford to cache more objects. Caching to disk is not
1224              really necessary if the database is on the same machine as the web server, but
1225              if it is on another machine we have to consider the network delay to connect
1226              to the database versus the disk access time. The default configuration does not
1227              use disk cache.
1228            </para>
1229
1230            <para>
1231            See also:
1232            </para>
1233            <itemizedlist>
1234            <listitem>
1235              <para>
1236              "Hibernate in action", chapter 5.3 "Caching theory and practice", page 175-194.
1237              </para>
1238            </listitem>
1239            <listitem>
1240              <para>
1241                Hibernate reference documentation: <ulink 
1242                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/performance.html#performance-cache">21.2. The Second Level Cache</ulink>
1243              </para>
1244            </listitem>
1245            </itemizedlist>
1246           
1247          </listitem>
1248        </varlistentry>
1249
1250        <varlistentry>
1251          <term>Proxies</term>
1252          <listitem>
1253            <para>
1254              Proxies are also used to gain performance, and they may have some impact on
1255              the code. Proxies are created at runtime (by Hibernate) as a subclass of the
1256              actual class but are not populated with data until some method of the object
1257              is called. The data is loaded from the database the first time a method other
1258              than <methodname>getId()</methodname> is called. Thus, we can avoid loading
1259              data that is not needed at a particular time.
1260            </para>
1261       
1262            <para>
1263              There can be a problem with using the <code>instanceof</code> operator with proxies
1264              and the table-per-class-hierarchy mapping. For example, if we have the abstract
1265              class <classname>Animal</classname> and subclasses <classname>Cat</classname>
1266              and <classname>Dog</classname>. The proxy of an <classname>Animal</classname> is a
1267              runtime generated subclass of <classname>Animal</classname>, since we do not know if it
1268              is a <classname>Cat</classname> or <classname>Dog</classname>. So,
1269              <code>x instanceof Dog</code> and <code>x instanceof Cat</code> would both return
1270              false. If we hadn't used a proxy, at least one of them would always be true.
1271            </para>
1272       
1273            <para>
1274              Proxies are only used when a not-null object is linked with many-to-one or
1275              one-to-one from another object. If we ask for a specific object by id, or by a
1276              query, we will never get a proxy. Therefore, it only makes sense to enable
1277              proxies for classes that can be linked from other classes. One-to-one links on
1278              the primary key where null is allowed silently disables the proxy feature,
1279              since Hibernate doesn't know if there is an object or not without querying
1280              the database.
1281            </para>
1282            <bridgehead>Proxy vs. cache</bridgehead>
1283            <para>
1284              The goal of a proxy and the second-level cache are the same: to avoid hitting the
1285              database. It is perfectly possible to enable both proxies and the cache for a
1286              class. Then we would start with a proxy and as soon as a method is called Hibernate
1287              would look in the second-level cache. Only if it is not there it would be loaded
1288              from the database. But, do we really need a proxy in the first place? Well, I think
1289              it might be better to use only the cache or only proxies. But, this also makes it
1290              even more important that the cache is configured correctly so there is a high
1291              probability that the object is already in the cache.
1292            </para>
1293           
1294            <para>
1295              If a class has been configured to use the second-level cache, we recommend
1296              that proxies are disabled. For child objects in a parent-child relationship proxies
1297              should be disabled, since they have no other links to them than from the parent.
1298              If a class can be linked as many-to-one from several other classes it makes sense
1299              to enable proxies. If we have a long chain of many-to-one relations it may also make
1300              sense to enable proxies at some level, even if the second-level cache is used.
1301              In that case we only need to create one proxy instead of looking up several objects
1302              in the cache. Also, think about how a particular class most commonly will be used
1303              in a client application. For example, it is very common to display the name of the
1304              owner of an item, but we are probably not interested in displaying quota
1305              information for that user. So, it makes sense to put users in the second-level
1306              cache and use proxies for quota information.
1307            </para>
1308
1309            <warning>
1310              <title>Batchable classes and stateless sessions</title>
1311              <para>
1312                Hibernate has a <emphasis>stateless session</emphasis> feature. A
1313                stateless session has no first-level cache and doesn't use the second-level
1314                cache either. This means that if we load an item with a stateless session
1315                Hibernate will always traverse many-to-one and one-to-one associations and
1316                load those objects as well, unless they are configured to use proxies.
1317              </para>
1318             
1319              <para>
1320                BASE use stateless sessions for loading <classname docapi="net.sf.basedb.core.data">BatchableData</classname>
1321                items (reporters, raw data and features)
1322                since they are many and we want to use as little memory as possible. Here it
1323                is required that proxies are enabled for all items that are linked from any of
1324                the batchable items, ie. <classname docapi="net.sf.basedb.core">RawBioAssay</classname>,
1325                <classname docapi="net.sf.basedb.core">ReporterType</classname>,
1326                <classname docapi="net.sf.basedb.core">ArrayDesignBlock</classname>, etc.
1327                If we don't do this Hibernate will generate multiple additional select
1328                statements for the same parent item which will affect performance
1329                in a bad way.
1330              </para>
1331             
1332              <para>
1333                On the other hand, the proxies created from a stateless session cannot later
1334                be initialised. We have to get the ID from the proxy and the load the object
1335                using the regular session. But this can also results in lots of additional select
1336                statements so if it is known before that we need some information it is recommended
1337                that a FETCH JOIN query is used so that we get fully initialized objects instead of
1338                proxies to begin with.
1339              </para>
1340            </warning>
1341            <para>
1342              Here is a table which summarises different settings for the second-level cache,
1343              proxies, batch fetching and many-to-one links. Batch fetching and many-to-one links
1344              are discussed later in this document.
1345            </para>
1346           
1347            <para>
1348              First, decide if the second-level cache should be enabled or not. Then, if
1349              proxies should be enabled or not. The table then gives a reasonable setting for
1350              the batch size and many-to-one mappings. NOTE! The many-to-one mappings are
1351              the links from other classes to this one, not links from this class.
1352            </para>
1353           
1354            <para>
1355              The settings in this table are not absolute rules. In some cases there might
1356              be a good reason for another combination. Please, write a comment about why
1357              the recommendations were not followed.
1358            </para>
1359           
1360            <table id="core_ref.rules.datalayer.cacheproxysettings">
1361              <title>Choosing cache and proxy settings</title>
1362              <tgroup cols="4">
1363                <colspec colname="cache" />
1364                <colspec colname="proxy" />
1365                <colspec colname="batchsize" />
1366                <colspec colname="outerjoin" />
1367               
1368                <thead>
1369                  <row>
1370                    <entry>Global configuration</entry>
1371                    <entry namest="proxy" nameend="batchsize">Class mapping</entry>
1372                    <entry>Many-to-one mapping</entry>
1373                  </row>
1374                  <row>
1375                    <entry>Cache</entry>
1376                    <entry>Proxy</entry>
1377                    <entry>Batch-size</entry>
1378                    <entry>Outer-join</entry>
1379                  </row>
1380                </thead>
1381                <tbody>
1382                  <row>
1383                    <entry>no</entry>
1384                    <entry>no*</entry>
1385                    <entry>yes</entry>
1386                    <entry>true</entry>
1387                  </row>
1388                  <row>
1389                    <entry>yes</entry>
1390                    <entry>no*</entry>
1391                    <entry>no</entry>
1392                    <entry>false</entry>
1393                  </row>
1394                  <row>
1395                    <entry>no</entry>
1396                    <entry>yes</entry>
1397                    <entry>yes</entry>
1398                    <entry>false</entry>
1399                  </row>
1400                  <row>
1401                    <entry>yes</entry>
1402                    <entry>yes</entry>
1403                    <entry>no</entry>
1404                    <entry>false</entry>
1405                  </row>
1406                </tbody>
1407              </tgroup>
1408            </table>
1409           
1410            <para>
1411              * = Do not use this setting for classes which are many-to-one linked from a batchable
1412              class.
1413            </para>
1414           
1415            <para>
1416            See also:
1417            </para>
1418            <itemizedlist>
1419            <listitem>
1420              <para>
1421              "Hibernate in action", chapter 4.4.6 "Selecting a fetching strategy in mappings", page 146-147
1422              </para>
1423            </listitem>
1424            <listitem>
1425              <para>
1426              "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
1427              </para>
1428            </listitem>
1429            <listitem>
1430              <para>
1431              Hibernate reference documentation: <ulink 
1432                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/performance.html#performance-fetching-proxies">21.1.3. Single-ended association proxies</ulink>
1433              </para>
1434            </listitem>
1435            </itemizedlist>
1436           
1437          </listitem>
1438        </varlistentry>
1439
1440        <varlistentry>
1441          <term>Hibernate mappings</term>
1442          <listitem>
1443            <para>
1444              We use Javadoc tags to specify the database mapping needed by Hibernate.
1445              The tags are processed by XDoclet at build time which generates the XML-based
1446              Hibernate mapping files.
1447            </para>
1448           
1449            <note>
1450              <title>XDoclet doesn't support all mappings</title>
1451              <para>
1452              The XDoclet that we use was developed to generate mapping files for
1453              Hibernate 2.x. Since then, Hibernate has released several 3.x versions,
1454              and the mapping file structure has changed. Some changes can be handled by
1455              generating a corresponding 2.x mapping and then converting it to a 3.x
1456              mapping at build time using simple search-and-replace operations.
1457              One such case is to update the DTD reference to the 3.0 version instead of
1458              the 2.0 version. Other changes can't use this approach. Instead we have to
1459              provide extra mappings inside an XML files. This is also needed if we need
1460              to use some of the new 3.x features that has no 2.x counterpart.
1461              </para>
1462            </note>
1463          </listitem>
1464        </varlistentry>
1465
1466        <varlistentry>
1467            <term>Class mapping</term>
1468            <listitem>
1469             
1470              <programlisting language="java">
1471/**
1472   This class holds information about any data...
1473   @author Your name
1474   @since 3.0
1475   @hibernate.class table="`Anys`" lazy="false" batch-size="10"
1476*/
1477public class AnyData
1478   extends CommonData
1479{
1480   // Rest of class code...
1481}
1482</programlisting>
1483
1484            <para>
1485              The class declaration must contain a <code>@hibernate.class</code> Javadoc entry
1486              where Hibernate can find the name of the table where items of this type are stored.
1487              The table name should generally be the same as the class name, without the ending
1488              <code>Data</code> and in a plural form. For example <classname docapi="net.sf.basedb.core.data">UserData</classname>
1489              → <code>Users</code>. The back-ticks (`) around the table name tells Hibernate
1490              to enclose the name in whatever the actual database manager uses for such things
1491              (back-ticks in MySQL, quotes for an ANSI-compatible database).
1492            </para>
1493           
1494            <important>
1495              <title>Always set the lazy attribute</title>
1496              <para>
1497                The <sgmltag class="attribute">lazy</sgmltag> attribute enables/disables
1498                proxies for the class. Do not forget to specify this attribute since the
1499                default value is true. If proxies are enabled, it may also make sense to
1500                specify a <sgmltag class="attribute">batch-size</sgmltag> attribute. Then
1501                Hibernate will load the specified number of items in each SELECT statement
1502                instead of loading them one by one. It may also make sense to specify a
1503                batch size when proxies are disabled, but then it would probably be even
1504                better to use eager fetching by setting <code>outer-join="true"</code>
1505                (see many-to-one mapping).
1506              </para>
1507 
1508              <para>
1509                Classes that are linked with a many-to-one association from a batchable
1510                class must specify <code>lazy="true"</code>. Otherwise the stateless session
1511                feature of Hibernate may result in a large number of SELECT:s for the same
1512                item, or even circular loops if two or more items references each other.
1513              </para>
1514            </important>
1515           
1516            <important>
1517              <title>Remember to enable the second-level cache</title>
1518              <para>
1519                Do not forget to configure settings for the second-level cache if this
1520                should be enabled. This is done in the <filename>hibernate.cfg.xml</filename>
1521                and <filename>ehcache.xml</filename>.
1522              </para>
1523            </important>
1524         
1525            <para>
1526            See also:
1527            </para>
1528           
1529            <itemizedlist>
1530            <listitem>
1531              <para>
1532              "Hibernate in action", chapter 3.3 "Defining the mapping metadata", page 75-87
1533              </para>
1534            </listitem>
1535            <listitem>
1536              <para>
1537              Hibernate reference documentation: <ulink 
1538                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#mapping-declaration-class">5.1.3. Entity</ulink>
1539              </para>
1540            </listitem>
1541            </itemizedlist>
1542           
1543          </listitem>
1544        </varlistentry>
1545
1546        <varlistentry>
1547          <term>Property mappings</term>
1548          <listitem>
1549            <para>
1550              Properties such as strings, integers, dates, etc. are mapped with
1551              the <code>@hibernate.property</code> Javadoc tag. The main purpose
1552              is to define the database column name. The column names should
1553              generally be the same as the get/set method name without the get/set prefix,
1554              and with upper-case letters converted to lower-case and an underscore inserted.
1555              Examples:
1556            </para>
1557           
1558            <itemizedlist>
1559            <listitem>
1560              <para>
1561                <methodname>getAddress()</methodname>
1562                → <code>column="`address`"</code>
1563              </para>
1564            </listitem>
1565            <listitem>
1566              <para>
1567                <methodname>getLoginComment()</methodname>
1568                → <code>column="`login_comment`"</code>
1569              </para>
1570            </listitem>
1571            </itemizedlist>
1572
1573            <para>
1574              The back-ticks (`) around the column name tells Hibernate to enclose
1575              the name in whatever the actual database manager uses for such things
1576              (back-ticks in MySQL, quotes for an ANSI-compatible database).
1577            </para>
1578           
1579            <bridgehead>String properties</bridgehead>
1580            <programlisting language="java">
1581public static int long MAX_STRINGPROPERTY_LENGTH = 255;
1582private String stringProperty;
1583/**
1584   Get the string property.
1585   @hibernate.property column="`string_property`" type="string"
1586      length="255" not-null="true"
1587*/
1588public String getStringProperty()
1589{
1590   return stringProperty;
1591}
1592public void setStringProperty(String stringProperty)
1593{
1594   this.stringProperty = stringProperty;
1595}
1596</programlisting>
1597
1598            <para>
1599              Do not use a greater value than 255 for the <sgmltag class="attribute">length</sgmltag>
1600              attribute. Some databases has that as the maximum length for character columns (ie. MySQL).
1601              If you need to store longer texts use <code>type="text"</code> instead. You can then skip
1602              the length attribute. Most databases will allow up to 65535 characters or more
1603              in a text field. Do not forget to specify the <sgmltag class="attribute">not-null</sgmltag> attribute.
1604            </para>
1605           
1606            <para>
1607              You should also define a public constant <constant>MAX_STRINGPROPERTY_LENGTH</constant>
1608              containing the maximum allowed length of the string.
1609            </para>
1610
1611            <bridgehead>Numerical properties</bridgehead>
1612           
1613            <programlisting language="java">
1614private int intProperty;
1615/**
1616   Get the int property.
1617   @hibernate.property column="`int_property`" type="int" not-null="true"
1618*/
1619public int getIntProperty()
1620{
1621   return intProperty;
1622}
1623public void setIntProperty(int intProperty)
1624{
1625   this.intProperty = intProperty;
1626}
1627</programlisting>
1628
1629            <para>
1630              It is also possible to use <classname>Integer</classname>, <classname>Long</classname>
1631              or <classname>Float</classname> objects instead of <classname>int</classname>,
1632              <classname>long</classname> and <classname>float</classname>. We have only used it
1633              if null values have some meaning.
1634            </para>
1635           
1636            <bridgehead>Boolean properties</bridgehead>
1637            <programlisting language="java">
1638private boolean booleanProperty;
1639/**
1640   Get the boolean property.
1641   @hibernate.property column="`boolean_property`"
1642      type="boolean" not-null="true"
1643*/
1644public boolean isBooleanProperty()
1645{
1646   return booleanProperty;
1647}
1648public void setBooleanProperty(boolean booleanProperty)
1649{
1650   this.booleanProperty = booleanProperty;
1651}
1652</programlisting>
1653            <para>
1654              It is also possible to use a <classname>Boolean</classname> object instead of
1655              <classname>boolean</classname>. It is only required if you absolutely need
1656              null values to handle special cases.
1657            </para>
1658
1659            <bridgehead>Date values</bridgehead>
1660           
1661            <programlisting language="java">
1662private Date dateProperty;
1663/**
1664   Get the date property. Null is allowed.
1665   @hibernate.property column="`date_property`" type="date" not-null="false"
1666*/
1667public Date getDateProperty()
1668{
1669   return dateProperty;
1670}
1671public void setDateProperty(Date dateProperty)
1672{
1673   this.dateProperty = dateProperty;
1674}
1675</programlisting>
1676       
1677          <para>
1678            Hibernate defines several other date and time types. We have decided to use
1679            the <code>type="date"</code> type when we are only interested in the date and
1680            the <code>type="timestamp"</code> when we are interested in both the date
1681            and time.
1682          </para>
1683         
1684          <para>
1685          See also:
1686          </para>
1687         
1688          <itemizedlist>
1689            <listitem>
1690              <para>
1691              "Hibernate in action", chapter 3.3.2 "Basic property and class mappings", page 78-84
1692              </para>
1693            </listitem>
1694            <listitem>
1695              <para>
1696              "Hibernate in action", chapter 6.1.1 "Built-in mapping types", page 198-200
1697              </para>
1698            </listitem>
1699            <listitem>
1700              <para>
1701              Hibernate reference documentation: <ulink 
1702                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#mapping-declaration-property">5.1.4. property</ulink>
1703              </para>
1704            </listitem>
1705            <listitem>
1706              <para>
1707              Hibernate reference documentation: <ulink 
1708                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#mapping-types-basictypes">5.2.2. Basic value types</ulink>
1709              </para>
1710            </listitem>
1711            </itemizedlist>
1712               
1713          </listitem>
1714        </varlistentry>
1715
1716        <varlistentry id="core_ref.rules.datalayer.manytoone">
1717          <term>Many-to-one mappings</term>
1718          <listitem>
1719            <programlisting language="java">
1720private OtherData other;
1721/**
1722   Get the other object.
1723   @hibernate.many-to-one column="`other_id`" not-null="true" outer-join="false"
1724*/
1725public OtherData getOther()
1726{
1727   return other;
1728}
1729public void setOther(OtherData other)
1730{
1731   this.other = other;
1732}
1733</programlisting>
1734         
1735          <para>
1736            We create a many-to-one mapping with the <code>@hibernate.many-to-one</code> tag.
1737            The most important attribute is the <code>column</code> attribute which specifies the name of
1738            the database column to use for the id of the other item. The back-ticks (`)
1739            around the column name tells Hibernate to enclose the name in whatever the
1740            actual database manager uses for such things (back-ticks in MySQL, quotes for
1741            an ANSI-compatible database).
1742          </para>
1743         
1744          <para>
1745            We also recommend that the <sgmltag class="attribute">not-null</sgmltag> attribute
1746            is specified. Hibernate will not check for null values, but it will generate table
1747            columns that allow or disallow null values. See it as en extra safety feature while debugging.
1748            It is also used to determine if Hibernate uses <code>LEFT JOIN</code> or
1749            <code>INNER JOIN</code> in SQL statements.
1750          </para>
1751         
1752          <para>
1753            The <sgmltag class="attribute">outer-join</sgmltag> attribute is important and affects how the
1754            cache and proxies are used. It can take three values: <constant>auto</constant>,
1755            <constant>true</constant> or <constant>false</constant>. If the value is
1756            <constant>true</constant> Hibernate will always use a join to load the linked
1757            object in a single select statement, overriding the cache and proxy settings.
1758            This value should only be used if the class being linked has disabled both
1759            proxies and the second-level cache, or if it is a link between a child
1760            and parent in a parent-child relationship. A <constant>false</constant> value is best when
1761            we expect the associated object to be in the second-level cache or proxying
1762            is enabled. This is probably the most common case. The auto setting uses a
1763            join if proxying is disabled otherwise it uses a proxy. Since we always
1764            know if proxying is enabled or not, this setting is not very useful. See
1765            <xref linkend="core_ref.rules.datalayer.cacheproxysettings" /> for the
1766            recommended settings.
1767          </para>
1768         
1769          <para>
1770            See also:
1771          </para>
1772           
1773          <itemizedlist>
1774            <listitem>
1775              <para>
1776              "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
1777              </para>
1778            </listitem>
1779            <listitem>
1780              <para>
1781              "Hibernate in action", chapter 4.4.5-4.4.6 "Fetching strategies", page 143-151
1782              </para>
1783            </listitem>
1784            <listitem>
1785              <para>
1786              "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
1787              </para>
1788            </listitem>
1789            <listitem>
1790              <para>
1791              Hibernate reference documentation: <ulink 
1792                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e7576">5.1.7. Mapping one to one and many to one associations</ulink>
1793              </para>
1794            </listitem>
1795            </itemizedlist>
1796          </listitem>
1797        </varlistentry>
1798
1799        <varlistentry id="core_ref.rules.datalayer.manytomany">
1800          <term>Many-to-many and one-to-many mappings</term>
1801          <listitem>
1802            <para>
1803              There are many variants of mapping many-to-many or one-to-many, and it is
1804              not possible to give examples of all of them. In the code these mappings
1805              are represented by <classname>Set</classname>:s, <classname>Map</classname>:s,
1806              <classname>List</classname>:s, or some other collection object. The most
1807              important thing to remember is that (in our application) the collections
1808              are only used to maintain the links between objects. They are (in most cases)
1809              not used for returning objects to client applications, as is the case with the
1810              many-to-one mapping.
1811            </para>
1812           
1813            <para>
1814              For example, if we want to find all members of a group we do not use the
1815              <code>GroupData.getUsers()</code> method, instead we will execute a database query
1816              to retrieve them. The reason for this design is that the logged in user may
1817              not have access to all users and we must add a permission checking filter
1818              before returning the user objects to the client application. Using a query
1819              will also allow client applications to specify sorting and filtering options
1820              for the users that are returned.
1821            </para>
1822            <programlisting language="java">
1823<![CDATA[
1824// RoleData.java
1825private Set<UserData> users;
1826/**
1827   Many-to-many from roles to users.
1828   @hibernate.set table="`UserRoles`" lazy="true"
1829   @hibernate.collection-key column="`role_id`"
1830   @hibernate.collection-many-to-many column="`user_id`"
1831      class="net.sf.basedb.core.data.UserData"
1832*/
1833public Set<UserData> getUsers()
1834{
1835   if (users == null) users = new HashSet<UserData>();
1836   return users;
1837}
1838void setUsers(Set&lt;UserData&gt; users)
1839{
1840   this.users = users;
1841}
1842]]>
1843</programlisting>
1844            <para>
1845              As you can see this mapping is a lot more complicated than what we have
1846              seen before. The most important thing is the <sgmltag class="attribute">lazy</sgmltag>
1847              attribute. It tells Hibernate to delay the loading of the related objects until the set
1848              is accessed. If the value is false or missing, Hibernate will load all objects
1849              immediately. There is almost never a good reason to specify something other
1850              than <code>lazy="true"</code>.
1851            </para>
1852           
1853            <para>
1854              Another important thing to remember is that the getter method must always return
1855              the same object that Hibernate passed to the setter method. Otherwise, Hibernate
1856              will not be able to detect changes made to the collection and as a result
1857              will have to delete and then recreate all links. To ensure that the collection
1858              object is not changed we have made the <methodname>setUsers()</methodname> method
1859              package private, and the <methodname>getUsers()</methodname> will create a
1860              new <classname>HashSet</classname> for us only if Hibernate didn't pass one
1861              in the first place.
1862            </para>
1863            <para>
1864              Let's also have a look at the reverse mapping:
1865            </para>
1866           
1867            <programlisting language="java">
1868<![CDATA[
1869// UserData.java
1870private Set<RoleData> roles;
1871/**
1872   Many-to-many from users to roles
1873   @hibernate.set table="`UserRoles`" lazy="true"
1874   @hibernate.collection-key column="`user_id`"
1875   @hibernate.collection-many-to-many column="`role_id`"
1876      class="net.sf.basedb.core.data.RoleData"
1877*/
1878Set<RoleData> getRoles()
1879{
1880   return roles;
1881}
1882void setRoles(Set<RoleData> roles)
1883{
1884   this.roles = roles;
1885}
1886]]>
1887</programlisting>
1888            <para>
1889              The only real difference here is that both the setter and the getter methods
1890              are package private. This is a safety measure because Hibernate will get confused if
1891              we modify both ends. Thus, we are forced to always add/remove users to/from
1892              the set in the <classname docapi="net.sf.basedb.core.data">RoleData</classname> object. The methods in the
1893              <classname docapi="net.sf.basedb.core.data">UserData</classname> class are never used by us.
1894              Note that we do not have to check for null and create a new set since Hibernate
1895              will handle null values as an empty set.
1896            </para>
1897            <para>
1898              So, why do we need the second collection at all? It is never accessed
1899              except by Hibernate, and since it is lazy it will always be "empty".
1900              The answer is that we want to use the relation in HQL statements.
1901              For example:
1902            </para>
1903           
1904            <programlisting language="sql">
1905SELECT ... FROM RoleData rle WHERE rle.users ...
1906SELECT ... FROM UserData usr WHERE usr.roles ...
1907</programlisting>
1908         
1909            <para>
1910              Without the second mapping, it would not have been possible to execute
1911              the second HQL statement. The inverse mapping is also important in
1912              parent-child relationships, where it is used to cascade delete the children
1913              if a parent is deleted (see below).
1914            </para>
1915
1916            <warning>
1917              <title>Do not use the inverse="true" setting</title>
1918              <para>
1919                Hibernate defines an <code>inverse="true"</code> setting that can be used with
1920                the <code>@hibernate.set</code> tag. If specified, Hibernate will ignore
1921                changes made to that collection. However, there is one problem with specifying
1922                this attribute. Hibernate doesn't delete entries in the association table,
1923                leading to foreign key violations if we try to delete a user. The only
1924                solutions are to skip the <code>inverse="true"</code> attribute or to
1925                manually delete the object from all collections on the non-inverse end.
1926                The first alternative is the most efficient since it only requires a
1927                single SQL statement. The second alternative must first load all associated
1928                objects and then issue a single delete statement for each association.
1929              </para>
1930             
1931              <para>
1932                In the "Hibernate in action" book they have a very different design
1933                where they recommend that changes are made in both collections. We don't
1934                have to do this since we are only interested in maintaining the links,
1935                which is always done in one of the collections.
1936              </para>
1937            </warning>
1938
1939            <bridgehead>Parent-child relationships</bridgehead>
1940 
1941            <para>
1942              When one or more objects are tightly linked to some other object we talk
1943              about a parent-child relationship. This kind of relationship becomes important
1944              when we are about to delete a parent object. The children cannot exist
1945              without the parent so they must also be deleted. Luckily, Hibernate can
1946              do this for us if we specify a <code>cascade="delete"</code> option for the link.
1947              This example is a one-to-many link between client and help texts.
1948            </para>
1949
1950            <programlisting language="java">
1951<![CDATA[
1952// ClientData.java
1953private Set<HelpData> helpTexts;
1954/**
1955   This is the inverse end.
1956   @see HelpData#getClient()
1957   @hibernate.set lazy="true" inverse="true" cascade="delete"
1958   @hibernate.collection-key column="`client_id`"
1959   @hibernate.collection-one-to-many class="net.sf.basedb.core.data.HelpData"
1960*/
1961Set<HelpData> getHelpTexts()
1962{
1963   return helpTexts;
1964}
1965
1966void setHelpTexts(Set<HelpData> helpTexts)
1967{
1968   this.helpTexts = helpTexts;
1969}
1970
1971// HelpData.java
1972private ClientData client;
1973/**
1974   Get the client for this help text.
1975   @hibernate.many-to-one column="`client_id`" not-null="true"
1976      update="false" outer-join="false" unique-key="uniquehelp"
1977*/
1978public ClientData getClient()
1979{
1980   return client;
1981}
1982public void setClient(ClientData client)
1983{
1984   this.client = client;
1985}
1986]]>
1987</programlisting>
1988            <para>
1989              This show both sides of the one-to-many mapping between parent and children.
1990              As you can see the <code>@hibernate.set</code> doesn't specify a table,
1991              since it is given by the <code>class</code> attribute of the
1992              <code>@hibernate.collection-one-to-many</code> tag.
1993            </para>
1994           
1995            <para>
1996              In a one-to-many mapping, it is always the "one" side that handles the
1997              link so the "many" side should always be mapped with <code>inverse="true"</code>.
1998            </para>
1999
2000            <bridgehead>Maps</bridgehead>
2001           
2002            <para>
2003              Another type of many-to-many mapping uses a <interfacename>Map</interfacename>
2004              for the collection. This kind of mapping is needed when the association between
2005              two objects needs additional data to be kept as part of the association.
2006              For example, the permission (stored as an integer value) given to users that
2007              are members of a project. Note that you should use a <interfacename>Set</interfacename>
2008              for mapping the inverse end.
2009            </para>
2010            <programlisting language="java">
2011<![CDATA[
2012// ProjectData.java
2013private Map<UserData, Integer> users;
2014/**
2015   Many-to-many mapping between projects and users including permission values.
2016   @hibernate.map table="`UserProjects`" lazy="true"
2017   @hibernate.collection-key column="`project_id`"
2018   @hibernate.index-many-to-many column="`user_id`"
2019      class="net.sf.basedb.core.data.UserData"
2020   @hibernate.collection-element column="`permission`" type="int" not-null="true"
2021*/
2022public Map<UserData, Integer> getUsers()
2023{
2024   if (users == null) users = new HashMap<UserData, Integer>();
2025   return users;
2026}
2027void setUsers(Map<UserData, Integer> users)
2028{
2029   this.users = users;
2030}
2031
2032// UserData.java
2033private Set<ProjectData> projects;
2034/**
2035   This is the inverse end.
2036   @see ProjectData#getUsers()
2037   @hibernate.set table="`UserProjects`" lazy="true"
2038   @hibernate.collection-key column="`user_id`"
2039   @hibernate.collection-many-to-many column="`project_id`"
2040      class="net.sf.basedb.core.data.ProjectData"
2041*/
2042Set<ProjectData> getProjects()
2043{
2044   return projects;
2045}
2046void setProjects(Set<ProjectData> projects)
2047{
2048   this.projects = projects;
2049}
2050]]>
2051</programlisting>
2052          <para>
2053            See also:
2054          </para>
2055         
2056          <itemizedlist>
2057            <listitem>
2058              <para>
2059              "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
2060              </para>
2061            </listitem>
2062            <listitem>
2063              <para>
2064              "Hibernate in action", chapter 6.2 "Mapping collections of value types", page 211-220
2065              </para>
2066            </listitem>
2067            <listitem>
2068              <para>
2069              "Hibernate in action", chapter 6.3.2 "Many-to-many associations", page 225-233
2070              </para>
2071            </listitem>
2072            <listitem>
2073              <para>
2074              Hibernate reference documentation: <ulink 
2075                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/collections.html">Chapter 7. Collection Mapping</ulink>
2076              </para>
2077            </listitem>
2078            <listitem>
2079              <para>
2080              Hibernate reference documentation: <ulink 
2081                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/example-parentchild.html">Chapter 24. Example: Parent/Child</ulink>
2082              </para>
2083            </listitem>
2084            </itemizedlist>
2085           
2086          </listitem>
2087        </varlistentry>
2088
2089        <varlistentry>
2090          <term>One-to-one mappings</term>
2091          <listitem>
2092            <para>
2093              A one-to-one mapping can come in two different forms, depending on if both
2094              objects should have the same id or not. We start with the case were the objects
2095              can have different id:s and the link is done with an extra column in one of
2096              the tables. The example is from the mapping between physical bioassays and
2097              arrayslides.
2098            </para>
2099
2100            <programlisting language="java">
2101// PhysicalBioAssayData.java
2102private ArraySlideData arrayslide;
2103/**
2104   Get the array slide
2105   @hibernate.many-to-one column="`arrayslide_id`" not-null="false"
2106      unique="true" outer-join="false"
2107*/
2108public ArraySlideData getArraySlide()
2109{
2110   return arrayslide;
2111}
2112public void setArraySlide(ArraySlideData arrayslide)
2113{
2114   this.arrayslide = arrayslide;
2115}
2116
2117// ArraySlideData.java
2118private PhysicalBioAssayData bioassay;
2119/**
2120   Get the bioassay.
2121   @hibernate.one-to-one property-ref="arraySlide"
2122*/
2123public PhysicalBioAssayData getPhysicalBioAssay()
2124{
2125   return hybridization;
2126}
2127public void setPhysicalBioAssay(PhysicalBioAssayData bioassay)
2128{
2129   this.bioassay = bioassay;
2130}         
2131</programlisting>
2132            <para>
2133              As you can see, we use the <code>@hibernate.many-to-one</code> mapping with <code>unique="true"</code>
2134              for the bioassay side. This will force the database to only allow the
2135              same array slide to be linked once. Also note that since, <code>not-null="false"</code>,
2136              null values are allowed and it doesn't matter which end of the relation that
2137              is inserted first into the database.
2138            </para>
2139            <para>
2140              For the array slide end we use a <code>@hibernate.one-to-one</code>
2141              mapping and specify the name of the property on the other end that we are
2142              linking to. One important thing to remember is to keep both ends synchronized.
2143              This should usually be done at the core layer and not in the data layer.
2144              Doing it in the data layer may effectively disable lazy loading if the synchronization
2145              code causes proxy initialization.
2146            </para>
2147
2148            <para>
2149              The second form of a one-to-one mapping is used when both objects must
2150              have the same id (primary key). The example is from the mapping between users
2151              and passwords.
2152            </para>
2153           
2154            <programlisting language="java">
2155// UserData.java
2156/**
2157   @hibernate.id column="`id`" generator-class="foreign"
2158   @hibernate.generator-param name="property" value="password"
2159*/
2160public int getId()
2161{
2162   return super.getId();
2163}
2164private PasswordData password;
2165/**
2166   Get the password.
2167   @hibernate.one-to-one class="net.sf.basedb.core.data.PasswordData"
2168      cascade="all" outer-join="false" constrained="true"
2169*/
2170public PasswordData getPassword()
2171{
2172   if (password == null)
2173   {
2174      password = new PasswordData();
2175      password.setUser(this);
2176   }
2177   return password;
2178}
2179void setPassword(PasswordData user)
2180{
2181   this.password = password;
2182}
2183
2184// PasswordData.java
2185private UserData user;
2186/**
2187   Get the user.
2188   @hibernate.one-to-one class="net.sf.basedb.core.data.UserData"
2189*/
2190public UserData getUser()
2191{
2192   return user;
2193}
2194void setUser(UserData user)
2195{
2196   this.user = user;
2197}
2198</programlisting>
2199         
2200            <para>
2201              In this case, we use the <code>@hibernate.one-to-one</code> mapping
2202              in both classes. The <code>constrained="true"</code> tag in <classname docapi="net.sf.basedb.core.data">UserData</classname>
2203              tells Hibernate to always insert the password first, and then the user. The makes it
2204              possible to use the (auto-generated) id for the password as the id
2205              for the user. This is controlled by the mapping for the <methodname>UserData.getId()</methodname>
2206              method, which uses the <code>foreign</code> id generator. This generator will look
2207              at the password property, ie. call <methodname>getPassword().getId()</methodname>
2208              to find the id for the user. Also note the initialisation code and <code>cascade="all"</code>
2209              tag in the <methodname>UserData.getPassword()</methodname> method. This is needed
2210              to avoid <classname>NullPointerException</classname>:s and to make sure everything
2211              is created and deleted properly.
2212            </para>
2213
2214            <para>
2215              See also:
2216            </para>
2217           
2218          <itemizedlist>
2219            <listitem>
2220              <para>
2221              "Hibernate in action", chapter 6.3.1 "One-to-one association", page 220-225
2222              </para>
2223            </listitem>
2224            <listitem>
2225              <para>
2226              Hibernate reference documentation: <ulink 
2227                url="http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e7576">5.1.7. 5.1.7. Mapping one to one and many to one associations</ulink>
2228              </para>
2229            </listitem>
2230            </itemizedlist>
2231
2232          </listitem>
2233        </varlistentry>
2234
2235        <varlistentry>
2236          <term>Class documentation</term>
2237          <listitem>
2238            <para>
2239              The documentation for the class doesn't have to be very lengthy. A single
2240              sentence is usually enough. Provide tags for the author, version, last modification date
2241              and a reference to the corresponding class in the <package>net.sf.basedb.core</package>
2242              package.
2243            </para>
2244           
2245            <programlisting language="java">
2246/**
2247   This class holds information about any items.
2248
2249   @author Your name
2250   @since 2.0
2251   @see net.sf.basedb.core.AnyItem
2252   @base.modified $Date: 2007-08-17 09:18:29 +0200 (Fri, 17 Aug 2007) $
2253   @hibernate.class table="`Anys`" lazy="false"
2254*/
2255public class AnyData
2256   extends CommonData
2257{
2258...
2259}
2260</programlisting>
2261          </listitem>
2262        </varlistentry>
2263
2264        <varlistentry>
2265          <term>Method documentation</term>
2266          <listitem>
2267            <para>
2268            Write a short one-sentence description for all public getter methods. You do not
2269            have document the parameters or the setter methods, since it would just be a
2270            repetition. Methods defined by interfaces are documented in the interface class.
2271            You should not have to write any documentation for those methods.
2272            </para>
2273           
2274            <para>
2275              For the inverse end of an association, which has only package private methods,
2276              write a notice about this and provide a link to to non-inverse end.
2277            </para>
2278           
2279            <programlisting language="java">
2280<![CDATA[
2281// UserData.java
2282private String address;
2283/**
2284   Get the address for the user.
2285   @hibernate.property column="`address`" type="string" length="255"
2286*/
2287public String getAddress()
2288{
2289   return address;
2290}
2291public void setAddress(String address)
2292{
2293   this.address = address;
2294}
2295
2296private Set<GroupData> groups;
2297/**
2298   This is the inverse end.
2299   @see GroupData#getUsers()
2300   @hibernate.set table="`UserGroups`" lazy="true" inverse="true"
2301   @hibernate.collection-key column="`user_id`"
2302   @hibernate.collection-many-to-many column="`group_id`"
2303      class="net.sf.basedb.core.data.GroupData"
2304*/
2305Set<GroupData> getGroups()
2306{
2307   return groups;
2308}
2309void setGroups(Set<GroupData> groups)
2310{
2311   this.groups = groups;
2312}
2313]]>
2314</programlisting>
2315          </listitem>
2316        </varlistentry>
2317
2318        <varlistentry>
2319          <term>Field documentation</term>
2320          <listitem>
2321            <para>
2322              Write a short one-sentence description for <code>public static final</code>
2323              fields. Private fields does not have to be documented.
2324            </para>
2325           
2326            <programlisting language="java">
2327/**
2328   The maximum length of the name of an item that can be
2329   stored in the database.
2330   @see #setName(String)
2331*/
2332public static final int MAX_NAME_LENGTH = 255;
2333</programlisting>
2334          </listitem>
2335        </varlistentry>
2336
2337        <varlistentry>
2338          <term>UML diagram</term>
2339          <listitem>
2340          <para>
2341            Groups of related classes should be included in an UML-like
2342            diagram to show how they are connected and work together.
2343            For example we group together users, groups, roles, etc. into an
2344            authentication UML diagram. It is also possible that a single class
2345            may appear in more than one diagram. For more information about
2346            how to create UML diagrams see
2347            <xref linkend="documentation.magicdraw" />.
2348          </para>
2349          </listitem>
2350        </varlistentry>
2351      </variablelist>
2352
2353    </sect2>
2354    <sect2 id="core_ref.rules.itemclass">
2355      <title>Item-class rules</title>
2356     
2357      <para>
2358        This document contains important information about item classes for the BASE developer.
2359        Item classes are classes that handles the business logic for the data classes in
2360        the <code>net.sf.basedb.core.data</code> package. In general there is one item class for
2361        each data class. When extending the database and creating new classes it is important
2362        that it follows the design of the already existing code.
2363      </para>
2364     
2365      <sect3 id="core_ref.rules.itemclass.basic">
2366        <title>Basic class and interface hierarchy</title>
2367     
2368        <para>
2369          To simplify the development of items, we have created a set of abstract classes
2370          and interfaces. A real class for an item must inherit from one of those classes
2371          and may implement any of the interfaces if needed. The strucure is similar to the
2372          structure found in the <code>net.sf.basedb.core.data</code> package
2373          (See <xref linkend="base_api.data" />).
2374        </para>
2375
2376        <figure id="core_ref.figures.basic">
2377          <title>Basic class and interface hierarchy</title>
2378          <screenshot>
2379            <mediaobject>
2380              <imageobject>
2381                <imagedata 
2382                  align="center"
2383                  fileref="figures/uml/corelayer.basic.png" format="PNG" />
2384              </imageobject>
2385            </mediaobject>
2386          </screenshot>
2387        </figure>
2388     
2389      </sect3>
2390     
2391      <sect3 id="core_ref.rules.itemclass.permissions">
2392        <title>Access permissions</title>
2393        <para>
2394          Each item class must be prepared to handle the access permissions for the
2395          logged in user. The base classes will do most of the required work, but
2396          not everything. There are four cases which the item class must be aware of:
2397        </para>
2398       
2399        <itemizedlist>
2400          <listitem><para>Initialise permissions in the <methodname>initPermissions()</methodname> method.</para></listitem>
2401          <listitem><para>Check for <emphasis>write</emphasis> permission in settter methods.</para></listitem>
2402          <listitem><para>Check for <emphasis>use</emphasis> permission when creating associations to other items.</para></listitem>
2403          <listitem><para>Make sure the <methodname>getQuery()</methodname> method returns only items with at least read permission.</para></listitem>
2404        </itemizedlist>
2405       
2406        <bridgehead id="core_ref.rules.itemclass.initpermissions">Initialise permissions</bridgehead>
2407       
2408        <para>
2409          The permissions for an item are initialised by a call to the <methodname>initPermissions()</methodname> 
2410          method. This method is called as soon as the item becomes attached to a <classname 
2411          docapi="net.sf.basedb.core">DbControl</classname> object, which is responsible for managing items
2412          in the database. The <methodname>initPermissions()</methodname> method shuld be overridden by
2413          subclasses that needs to grant or deny permissions that is not granted or denied by default.
2414          When overriding the <methodname>initPermissions()</methodname> method it is important to:
2415        </para>
2416       
2417        <itemizedlist>
2418          <listitem>
2419            <para>
2420              Combine the additional permissions with those that was passed as parameters.
2421              Use the binary OR operator ( | ) with the result from the <code>Permission.grant()</code>
2422              and <code>Permission.deny()</code> methods to do this.
2423            </para>
2424          </listitem>
2425          <listitem>
2426            <para>
2427              Call <code>super.initPermissions()</code>. Otherwise, no permissions will be set all,
2428              resulting in an <classname docapi="net.sf.basedb.core">PermissionDeniedException</classname> almost immediately.
2429            </para>
2430          </listitem>
2431        </itemizedlist>
2432       
2433        <para>
2434          Here is an example from the <classname docapi="net.sf.basedb.core">OwnedItem</classname> class.
2435          If the currently logged in user is the same as the owner of the item, <constant>DELETE</constant>,
2436          <constant>SET_OWNER</constant> and <constant>SET_PERMISSION</constant> permissions are granted.
2437          Remember that delete permission also implies <constant>READ</constant>, <constant>USE</constant>
2438          and <constant>WRITE</constant> permissions.
2439        </para>
2440       
2441        <programlisting language="java">
2442<![CDATA[
2443// OwnedItem.java
2444void initPermissions(int granted, int denied)
2445{
2446   UserData owner = getData().getOwner();
2447   // owner may be null for new items
2448   if (owner != null && owner.getId() == getSessionControl().getLoggedInUserId())
2449   {
2450      granted |= Permission.grant(Permission.DELETE, Permission.SET_OWNER,
2451         Permission.SET_PERMISSION);
2452   }
2453   super.initPermissions(granted, denied);
2454}       
2455]]>
2456</programlisting>
2457       
2458       
2459        <para>
2460          Here is another example for <classname docapi="net.sf.basedb.core">News</classname> items,
2461          which grants read permission to anyone (even if not logged in) if today is between
2462          the start and end date of the news entry:
2463        </para>
2464       
2465        <programlisting language="java">
2466<![CDATA[
2467// News.java
2468void initPermissions(int granted, int denied)
2469   throws BaseException
2470{
2471   long today = new Date().getTime();
2472   long startDate = getData().getStartDate().getTime();
2473   long endDate = getData().getEndDate() == null ? 0 : getData().getEndDate().getTime()+24*3600*1000;
2474   if (startDate <= today && (endDate == 0 || today <= endDate))
2475   {
2476      granted |= Permission.grant(Permission.READ);
2477   }
2478   super.initPermissions(granted, denied);
2479}
2480]]>
2481</programlisting>
2482       
2483        <para>
2484          A third example from the <classname docapi="net.sf.basedb.core">Help</classname> class which
2485          is a child item to <classname docapi="net.sf.basedb.core">Client</classname>. Normally you will
2486          get <constant>READ</constant> permission on all child items if you have <constant>READ</constant>
2487          permission on the parent item, and <constant>CREATE</constant>, <constant>WRITE</constant> and
2488          <constant>DELETE</constant> permissions if you have <constant>WRITE</constant> permission on the parent item.
2489          In this case you don't have to override the <methodname>initPermissions()</methodname> method
2490          if the child class extends the <classname docapi="net.sf.basedb.core">ChildItem</classname> class.
2491          Instead, it should implement the <methodname>getSharedParent()</methodname> 
2492          method. The <methodname>ChildItem.initPermissions()</methodname> will take care of checking the
2493          permissions on the parent instead of on the child. Note that this only works if the parent itself
2494          hasn't overridden the <methodname>initPermissions()</methodname> method, since that method is never
2495          called in this case.
2496        </para>
2497       
2498        <programlisting language="java">
2499// Help.java
2500public class Help
2501   extends ChildItem
2502   implements Nameable
2503
2504...
2505
2506SharedData getSharedParent()
2507{
2508   return getData().getClient();
2509}
2510</programlisting>
2511       
2512        <bridgehead>Permissions granted by the base classes</bridgehead>
2513       
2514        <variablelist>
2515          <varlistentry>
2516            <term><classname docapi="net.sf.basedb.core">BasicItem</classname></term>
2517            <listitem>
2518              <para>
2519              This class will grant or deny permissions as the are defined by the roles the logged
2520              in user is a member of. If a subclass extend directly from this class, it is common
2521              that the <methodname>initPermissions()</methodname> method needs to be overridden.
2522              </para>
2523            </listitem>
2524          </varlistentry>
2525       
2526          <varlistentry>
2527            <term><classname docapi="net.sf.basedb.core">ChildItem</classname></term>
2528            <listitem>
2529              <para>
2530              This class grant <constant>READ</constant> permission if the logged in user has
2531              <constant>READ</constant> permission on the parent item, and <constant>CREATE</constant>,
2532              <constant>WRITE</constant> and <constant>DELETE</constant> 
2533              permission if the logged in user has <constant>WRITE</constant> (configurable)
2534              permission on the parent item.
2535              </para>
2536            </listitem>
2537          </varlistentry>
2538       
2539          <varlistentry>
2540            <term><classname docapi="net.sf.basedb.core">OwnedItem</classname></term>
2541            <listitem>
2542              <para>
2543              The owner of an item gets <constant>DELETE</constant>, <constant>SET_OWNER</constant> 
2544              and <constant>SET_PERMISSION</constant> permissions. Delete permission also implies read,
2545              use and write permissions. Subclasses to this class usually doesn't have to overide the
2546              <methodname>initPermissions()</methodname> method.
2547              </para>
2548            </listitem>
2549          </varlistentry>
2550       
2551          <varlistentry>
2552            <term><classname docapi="net.sf.basedb.core">SharedItem</classname></term>
2553            <listitem>
2554              <para>
2555              The logged in user get permissions as specified in the associated <classname docapi="net.sf.basedb.core">ItemKey</classname>
2556              and/or <classname docapi="net.sf.basedb.core">ProjectmKey</classname>. Subclasses to this class usually doesn't
2557              have to overide the <methodname>initPermissions()</methodname> method.
2558              </para>
2559            </listitem>
2560          </varlistentry>
2561        </variablelist>
2562       
2563        <bridgehead>Checking for write permission in setter methods</bridgehead>
2564       
2565        <para>
2566          An item class is required to check for <constant>WRITE</constant> permission in each
2567          method that modifies the state from a public method. Example:
2568        </para>
2569       
2570        <programlisting language="java">
2571public void setName(String name)
2572   throws PermissionDeniedException
2573{
2574   checkPermission(Permission.WRITE);
2575   // ... rest of code
2576}
2577</programlisting>
2578       
2579        <warning>
2580          <para>
2581            If you forget this, an unauthorised user may be able to change the properties of an item.
2582            <constant>WRITE</constant> permissions are not checked in any other central place in the
2583            core code. Place the permission check on the first line in the method, before any data validation.
2584            This will make it easier to spot places where the permission check is forgotten.
2585          </para>
2586        </warning>
2587       
2588        <bridgehead>Checking for use permission when creating associations</bridgehead>
2589        <para>
2590          An item class is required to check for <constant>USE</constant> permission on associated objects
2591          in each method that modifies the association from a public method. Example from the
2592          <classname docapi="net.sf.basedb.core">Protocol</classname> class:
2593        </para>
2594       
2595        <programlisting language="java">
2596public void setFile(File file)
2597   throws PermissionDeniedException
2598{
2599   checkPermission(Permission.WRITE);
2600   if (file != null) file.checkPermission(Permission.USE);
2601   getData().setFile(file == null ? null : file.getData());
2602}
2603</programlisting>
2604        <warning>
2605          <para>
2606            If you forget this, an unauthorised user may be able to change the association of an item.
2607            <constant>USE</constant> permissions are not checked in any other central place in the core
2608            code. Place the permission check as early in the method as possible after it has been validated
2609            that the value isn't null.
2610          </para>
2611        </warning>
2612       
2613        <bridgehead id="core_ref.rules.itemclass.getquery">Making sure the getQuery() method only returns items with read permission</bridgehead>
2614       
2615        <para>
2616          This method can be one of the most complex ones of the entire class. The query it generates
2617          must always be compatible with the <methodname>initPermissions()</methodname> method. Ie.
2618          it must not return any items for which the <methodname>initPermissions()</methodname> method doesn't
2619          grant <constant>READ</constant> permission. And the other way around, if the <methodname>initPermissions()</methodname>
2620          method grants <constant>READ</constant> permission to and item, the query should be able to return it.
2621          The simplest case is if you doesn't override the <methodname>initPermissions()</methodname> method in
2622          such a way that it affects <constant>READ</constant> permissions. In this case you can just create a
2623          query and return it as it is. The query implementation will take care of the rest.
2624        </para>
2625       
2626        <programlisting language="java">
2627<![CDATA[
2628// Client.java
2629public static ItemQuery<Client> getQuery()
2630{
2631   return new ItemQuery<Client>(Client.class);
2632}
2633]]>
2634</programlisting>
2635
2636        <para>
2637          A common case is when an item is the child of another item. Usually the parent is a
2638          <classname docapi="net.sf.basedb.core">Shareable</classname> item which means that we optimally
2639          should check the item and project keys on the parent when returning the children. But, this is a
2640          rather complex operation, so in this case we have choosen a different approach. The
2641          <methodname>getQuery()</methodname> method of child items must take a parameter of the parent type.
2642          The query can the safely return all children of that parent, since having a reference to the parent item,
2643          means that <constant>READ</constant> permission is granted. A null value for the parent is allowed, but
2644          then we fall back to check for role permissions only (with the help of a <classname 
2645          docapi="net.sf.basedb.core">ChildFilter</classname> object).
2646        </para>
2647        <programlisting language="java">
2648<![CDATA[
2649// Help.java
2650private static final QueryRuntimeFilter RUNTIME_FILTER =
2651   new QueryRuntimeFilterFactory.ChildFilter(Item.HELP, Item.CLIENT);
2652
2653public static ItemQuery<Help> getQuery(Client client)
2654{
2655   ItemQuery<Help> query = null;
2656   if (client != null)
2657   {
2658      query = new ItemQuery<Help>(Help.class, null);
2659      query.restrictPermanent(
2660         Restrictions.eq(
2661            Hql.property("client"),
2662            Hql.entity(client)
2663         )
2664      );
2665   }
2666   else
2667   {
2668      query = new ItemQuery<Help>(Help.class, RUNTIME_FILTER);
2669   }
2670   return query;
2671}
2672]]>
2673</programlisting>
2674
2675        <para>
2676          There are many other variants of the <methodname>getQuery()</methodname> method, for example all items
2677          having to with the authentication, <classname docapi="net.sf.basedb.core">User</classname>,
2678          <classname docapi="net.sf.basedb.core">Group</classname>, <classname docapi="net.sf.basedb.core">Role</classname>, etc.
2679          must check the logged in user's membership. We don't show any more examples here. Take a look in the source code
2680          if you want more information. You can also read <xref linkend="api_overview.query_api" /> for more examples.
2681        </para>
2682
2683      </sect3>
2684     
2685      <sect3 id="core_ref.rules.itemclass.validation">
2686        <title>Data validation</title>
2687       
2688        <para>
2689          An item class must validate all data that is passed to it as parameters. There are three types of validation:
2690        </para>
2691       
2692        <orderedlist>
2693          <listitem>
2694            <para>
2695            Validation of properties that are independent of other properties. For example, the length of a string or the value of number.
2696            </para>
2697          </listitem>
2698          <listitem>
2699            <para>
2700            Validation of properties that depends on other properties on the same object. For example, we have
2701            properties for the row and column counts, and then an array of linked objects for each position.
2702            </para>
2703          </listitem>
2704          <listitem>
2705            <para>
2706            Validation of properties that depends on the values of other objects. For example, the login of a
2707            user must be unique among all users.
2708            </para>
2709          </listitem>
2710        </orderedlist>
2711       
2712        <para>
2713          For each of these types of validation we have choosen a strategy that is as simple as possible
2714          and doesn't force us to complex requirements on the code for objects. First, we may note that
2715          case 1 is very common, case 2 is very uncommon, and case 3 is just a bit more common than case 2.
2716        </para>
2717       
2718        <bridgehead>Case 1 validation</bridgehead>
2719       
2720        <para>
2721          For case 1 we choose to make the validation in the set method for each property. Example:
2722        </para>
2723       
2724        <programlisting language="java">
2725public void setName(String name)
2726   throws InvalidDataException
2727{
2728   checkPermission(Permission.WRITE);
2729   // Null is not allowed
2730   if (name == null) throw new InvalidUseOfNullException("name");
2731   // The name must not be too long
2732   if (name.length > MAX_NAME_LENGTH)
2733   {
2734      throw new StringTooLongException("name", name, MAX_NAME_LENGTH);
2735   }
2736   getData().setName(name);
2737}
2738// Note! In this case we should actually use NameableUtil instead
2739</programlisting>
2740     
2741        <para>
2742          This will take care of all case 1 validation except that we cannot check properties that
2743          doesn't allow null values if the method never is called. To solve this problem we have
2744          two strategies:
2745        </para>
2746       
2747        <itemizedlist>
2748          <listitem>
2749            <para>
2750            Provide a default value that is set in the constructor. For example the name
2751            of a new user can be initilised to "New user".
2752            </para>
2753          </listitem>
2754          <listitem>
2755            <para>
2756              Use constructor methods with parameters for required objects.
2757            </para>
2758          </listitem>
2759        </itemizedlist>
2760       
2761        <para>
2762          Which strategy to use is decided from case to case. Failure to validate a property will usually
2763          result in a database exception, so no real harm is done, except that we don't want to show the
2764          ugly error messages to our users. The <classname docapi="net.sf.basedb.core">News</classname>
2765          class uses a mix of the two strategies:
2766        </para>
2767       
2768        <programlisting language="java">
2769// News.java
2770public static News getNew(DbControl dc, Date startDate, Date newsDate)
2771{
2772   News n = dc.newItem(News.class);
2773   n.setName("New news");
2774   n.setStartDate(startDate);
2775   n.setNewsDate(newsDate);
2776   n.getData().setEntryDate(new Date());
2777   return n;
2778}
2779...
2780public void setStartDate(Date startDate)
2781   throws PermissionDeniedException, InvalidDataException
2782{
2783   checkPermission(Permission.WRITE);
2784   getData().setStartDate(DateUtil.setNotNullDate(startDate, "startDate"));
2785}
2786...
2787</programlisting>
2788     
2789        <bridgehead>Case 2 validation</bridgehead>
2790       
2791        <para>
2792          This case requires interception of saves and updates and a call to the <methodname>validate()</methodname>
2793          method on the item. This automatically done on items which implements the <interfacename 
2794          docapi="net.sf.basedb.core">Validatable</interfacename> interface. Internally this functionality is
2795          implemented by the <classname docapi="net.sf.basedb.core">DbControl</classname> class, which keeps a
2796          "commit queue" that holds all loaded items that implements the <interfacename 
2797          docapi="net.sf.basedb.core">Validatable</interfacename> interface. When <methodname>DbControl.commit()</methodname> 
2798          is called, the queue is iterated and the <methodname>validate()</methodname> method is called for each item.
2799          Here is another example from the <classname docapi="net.sf.basedb.core">News</classname> class which must
2800          validate that the three dates (startDate, newsData and endData) are in proper order:
2801        </para>
2802        <programlisting language="java">
2803<![CDATA[
2804// News.java
2805void validate()
2806   throws InvalidDataException, BaseException
2807{
2808   super.validate();
2809   Date startDate = getData().getStartDate();
2810   Date newsDate = getData().getNewsDate();
2811   Date endDate = getData().getEndDate();
2812   if (startDate.after(newsDate))
2813   {
2814      throw new InvalidDataException("Invalid date. startDate is after newsDate.");
2815   }
2816   if (endDate != null && newsDate.after(endDate))
2817   {
2818      throw new InvalidDataException("Invalid date. newsDate is after endDate.");
2819   }
2820}
2821]]>
2822</programlisting>
2823       
2824        <bridgehead>Case 3 validation</bridgehead>
2825        <para>
2826          Usually, we do not bother with checking for this case, but delegates to the database
2827          to do the check. The reason that we do not bother to check for this case is that we can't
2828          be sure to succeed even if we first check the database. It is possible that during the time
2829          between our check and the actual insert or update, another transaction has already inserted
2830          another object into the database that violates the check. This is not perfect and the error
2831          messages are a bit ugly, but under the circumstances it is the best we can do.
2832        </para>
2833      </sect3>
2834     
2835      <sect3 id="core_ref.rules.itemclass.transactions">
2836        <title>Participating in transactions</title>
2837       
2838        <para>
2839          Sometimes it is neccessary for an item to intercept certain events. For example,
2840          the <classname docapi="net.sf.basedb.core">File</classname> object needs to know
2841          if a transaction has been completed or rollbacked so it can clean up temporary
2842          files that have been used. We have created the <interfacename 
2843          docapi="net.sf.basedb.core">Transactional</interfacename> interface, which is a tagging
2844          interface that tells the core to call certain methods on the item at certain events.
2845          The interface doesn't contain any methods, the item class needs to override methods
2846          from the <classname docapi="net.sf.basedb.core">BasicItem</classname> class. The following
2847          events/methods have been defined:
2848        </para>
2849       
2850        <note>
2851          <para>
2852          The methods are always called for new items and items that are about to be
2853          deleted. It is only neccessary for an item to implement the <interfacename 
2854          docapi="net.sf.basedb.core">Transactional</interfacename> interface if it
2855          needs to act on <constant>UPDATE</constant> events.
2856          </para>
2857        </note>
2858       
2859        <variablelist>
2860          <varlistentry>
2861            <term>onBeforeCommit(Action)</term>
2862            <listitem>
2863              <para>
2864                This method is called before a commit is issued to Hibernate. It should be used by an
2865                item when it needs to update dependent objects before anything is written to the database.
2866                Note that nothing has been sent to the database yet and new items has not got an id when
2867                this method is called. If you override this method you must call <methodname>super.onBeforeCommit()</methodname> 
2868                to allow the superclass to do whatever it needs to do. Here is an example from the
2869                <classname docapi="net.sf.basedb.core">OwnedItem</classname> class which sets the owner to the
2870                currently logged in user, if no owner has been explicitely specified:
2871              </para>
2872             
2873              <programlisting language="java">
2874<![CDATA[
2875void onBeforeCommit(Transactional.Action action)
2876   throws NotLoggedInException, BaseException
2877{
2878   super.onBeforeCommit(action);
2879   if (action == Transactional.Action.CREATE && getData().getOwner() == null)
2880   {
2881      org.hibernate.Session session = getDbControl().getHibernateSession();
2882      int loggedInuserId = getSessionControl().getLoggedInUserId();
2883      UserData owner =
2884         HibernateUtil.loadData(session, UserData.class, loggedInuserId);
2885      if (owner == null) throw new NotLoggedInException();
2886      getData().setOwner(owner);
2887   }
2888}
2889]]>
2890</programlisting>
2891            </listitem>
2892          </varlistentry>
2893         
2894          <varlistentry>
2895            <term>setProjectDefaults(Project)</term>
2896            <listitem>
2897              <para>
2898                This method is called before inserting new items into the database
2899                to allow items to propagate default values from the active project.
2900                The method is only called when a project is active. Subclasses should
2901                always call <methodname>super.setProjectDefaults()</methodname>
2902                and should only set default values that hasn't been explicitely set
2903                by client code (including <code>setFoo(null)</code> calls).
2904              </para>
2905             
2906              <note>
2907                <para>
2908                With few exceptions a project can only hold <classname docapi="net.sf.basedb.core">ItemSubtype</classname>
2909                items as default values. This means that the item that is going to use the default
2910                value should implement the <interfacename docapi="net.sf.basedb.core">Subtypeable</interfacename>
2911                interface and list the other related item types in the <code>@SubtypableRelatedItems</code>
2912                annotation.
2913                </para>
2914              </note>
2915             
2916              <programlisting language="java">
2917<![CDATA[
2918// DerivedBioAssaySet.java
2919@Override
2920@SubtypableRelatedItems({Item.PHYSICALBIOASSAY, Item.DERIVEDBIOASSAYSET, Item.SOFTWARE, Item.HARDWARE, Item.PROTOCOL})
2921public ItemSubtype getItemSubtype()
2922{
2923  return getDbControl().getItem(ItemSubtype.class, getData().getItemSubtype());
2924}
2925
2926/**
2927  Set protocol, hardware and software from project default settings.
2928*/
2929@Override
2930void setProjectDefaults(Project activeProject)
2931  throws BaseException
2932{
2933  super.setProjectDefaults(activeProject);
2934  if (!hasPermission(Permission.WRITE)) return;
2935   
2936  DbControl dc = getDbControl();
2937  if (!protocolHasBeenSet)
2938  {
2939    ProtocolData protocol =
2940      (ProtocolData)activeProject.findDefaultRelatedData(dc, this, Item.PROTOCOL, false);
2941    if (protocol != null)
2942    {
2943      getData().setProtocol(protocol);
2944      protocolHasBeenSet = true;
2945    }
2946  }
2947  if (!hardwareHasBeenSet)
2948  {
2949    HardwareData hardware =
2950      (HardwareData)activeProject.findDefaultRelatedData(dc, this, Item.HARDWARE, false);
2951    if (hardware != null)
2952    {
2953      getData().setHardware(hardware);
2954      hardwareHasBeenSet = true;
2955    }
2956  }
2957  if (!softwareHasBeenSet)
2958  {
2959    SoftwareData software =
2960      (SoftwareData)activeProject.findDefaultRelatedData(dc, this, Item.SOFTWARE, false);
2961    if (software != null)
2962    {
2963      getData().setSoftware(software);
2964      softwareHasBeenSet = true;
2965    }
2966  }
2967}
2968]]>
2969</programlisting>
2970            </listitem>
2971          </varlistentry>
2972
2973          <varlistentry>
2974            <term>onAfterInsert()</term>
2975            <listitem>
2976              <para>
2977                This method is called on all items directly after Hibernate has inserted
2978                it into the database. This method can be used in place of the
2979                <methodname>onBeforeCommit()</methodname> in case the id is needed.
2980              </para>
2981            </listitem>
2982          </varlistentry>
2983
2984          <varlistentry>
2985            <term>onAfterCommit(Action)</term>
2986            <listitem>
2987              <para>
2988                This method is called after a successful commit has been issued to Hibernate. It should be
2989                used by an item which needs to do additional processing. For example the
2990                <classname docapi="net.sf.basedb.core">File</classname> object may need to cleanup temporary files.
2991                This method should not use the database and it must not fail, since it is impossible to rollback
2992                anything that has already been committed to the database. If the method fails, it should log
2993                an exception with the <methodname>Application.log()</methodname> method.
2994              </para>
2995            </listitem>
2996          </varlistentry>
2997
2998          <varlistentry>
2999            <term>onRollback(Action)</term>
3000            <listitem>
3001              <para>
3002                This method is called after an unsuccessful commit has been issued to Hibernate. The same rules as
3003                for the <methodname>onAfterCommit()</methodname> method applies to this method.
3004              </para>
3005            </listitem>
3006          </varlistentry>
3007        </variablelist>
3008       
3009        <para>
3010          Internally this functionality is implemented by the <classname docapi="net.sf.basedb.core">DbControl</classname>
3011          class, which keeps a "commit queue" that holds all new objects, all objects that are about to be deleted
3012          and all objects that implements the <interfacename docapi="net.sf.basedb.core">Transactional</interfacename> 
3013          interface. When <methodname>DbControl.commit()</methodname> is called, the queue is iterated and
3014          <methodname>onBeforeCommit()</methodname> is called for each item, and then
3015          either <methodname>onAfterCommit()</methodname> or <methodname>onRollback()</methodname>.
3016          The <classname docapi="net.sf.basedb.core.Transactional">Action</classname> parameter is of an
3017          enumeration type which can hae three different values:
3018        </para>
3019
3020
3021        <itemizedlist>
3022          <listitem>
3023            <para>
3024            <constant>CREATE</constant>: This is a new item which is saved to the database for the first time.
3025            </para>
3026          </listitem>
3027          <listitem>
3028            <para>
3029            <constant>UPDATE</constant>: This is an existing item, which has been modified.
3030            </para>
3031          </listitem>
3032          <listitem>
3033            <para>
3034            <constant>DELETE</constant>: This is an existing item, which is now being deleted from the database
3035            </para>
3036          </listitem>
3037        </itemizedlist>
3038
3039      </sect3>
3040     
3041      <sect3 id="core_ref.rules.itemclass.template">
3042        <title>Template code for item classes</title>
3043       
3044        <para>
3045          The <ulink url="../../examples/AnyItem.java.txt">AnyItem.java</ulink> and <ulink 
3046          url="../../examples/AChildItem.java.txt">AChildItem.java</ulink> files
3047          contains two complete item classes with lots of template methods. Please copy and paste as much as you want
3048          from these, but do not forget to change the specific details.
3049        </para>
3050       
3051        <bridgehead>Class declaration</bridgehead>
3052       
3053        <para>
3054          An item class should extend one of the four classes: <classname docapi="net.sf.basedb.core">BasicItem</classname>,
3055          <classname docapi="net.sf.basedb.core">OwnedItem</classname>, <classname docapi="net.sf.basedb.core">SharedItem</classname>
3056          and <classname docapi="net.sf.basedb.core">CommonItem</classname>. Which one depends on what combination of
3057          interfaces are needed for that item. The most common situation is probably to extend the <classname 
3058          docapi="net.sf.basedb.core">CommonItem</classname> class. Do not forget to include the GNU licence and
3059          copyright statement. Also note that the corresponding data layer class is specified as a
3060          generics parameter of the superclass.
3061        </para>
3062       
3063        <programlisting language="java">
3064<![CDATA[
3065/*
3066  $Id $
3067
3068  Copyright (C) 2011 Your name
3069
3070  This file is part of BASE - BioArray Software Environment.
3071  Available at http://base.thep.lu.se/
3072
3073  BASE is free software; you can redistribute it and/or
3074  modify it under the terms of the GNU General Public License
3075  as published by the Free Software Foundation; either version 3
3076  of the License, or (at your option) any later version.
3077
3078  BASE is distributed in the hope that it will be useful,
3079  but WITHOUT ANY WARRANTY; without even the implied warranty of
3080  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3081  GNU General Public License for more details.
3082
3083  You should have received a copy of the GNU General Public License
3084  along with BASE. If not, see <http://www.gnu.org/licenses/>.
3085*/
3086package net.sf.basedb.core;
3087import net.sf.basedb.core.data.AnyData;
3088/**
3089  This class is used to represent an AnyItem in BASE.
3090
3091  @author Your name
3092  @since 3.0
3093  @see AnyData
3094  @base.modified $Date$
3095*/
3096public class AnyItem
3097  extends CommonItem<AnyData>
3098{
3099  ...
3100}
3101]]>
3102</programlisting>
3103
3104        <bridgehead>Static methods and fields</bridgehead>
3105       
3106        <variablelist>
3107          <varlistentry>
3108            <term>getNew(DbControl)</term>
3109            <listitem>
3110              <para>
3111              This method is used to create a new item. The new item must be created by calling the
3112              <methodname>DbControl.newItem()</methodname>.
3113              </para>
3114             
3115              <programlisting language="java">
3116<![CDATA[
3117/**
3118  Create a new <code>AnyItem</code> item.
3119 
3120  @param dc The <code>DbControl</code> which will be used for
3121    permission checking and database access
3122  @return The new <code>AnyItem</code> item
3123  @throws BaseException If there is an error
3124*/
3125public static AnyItem getNew(DbControl dc)
3126  throws BaseException
3127{
3128  AnyItem a = dc.newItem(AnyItem.class);
3129  a.setName("New any item");
3130  return a;
3131}
3132]]>
3133</programlisting>
3134              <para>
3135                The method must initialise all not-null properties to a sensible default values or it may take values as parameters:
3136              </para>
3137              <programlisting language="java">
3138<![CDATA[
3139// User.java
3140public static User getNew(DbControl dc, String login, String password)
3141   throws BaseException
3142{
3143   User u = dc.newItem(User.class);
3144   u.setName("New user");
3145   u.setLogin(login);
3146   u.setPassword(password);
3147   int defaultQuotaId = SystemItems.getId(Quota.DEFAULT);
3148   org.hibernate.Session session = dc.getHibernateSession();
3149   QuotaData defaultQuota =
3150      HibernateUtil.loadData(session, QuotaData.class, defaultQuotaId);
3151   u.getData().setQuota(defaultQuota);
3152   return u;
3153}
3154]]>
3155</programlisting>
3156              <para>
3157                When the default value is an association to another item, use the data object
3158                (<classname docapi="net.sf.basedb.core.data">QuotaData</classname>) not the item object
3159                (<classname docapi="net.sf.basedb.core">Quota</classname>) to create the association.
3160                The reason for this is that the logged in user may not have read permission to the default
3161                object. Ie. The logged in user may have permission to create users, but not permission to
3162                read quota.
3163              </para>
3164
3165            </listitem>
3166          </varlistentry>
3167       
3168          <varlistentry>
3169            <term>getById(DbControl, int)</term>
3170            <listitem>
3171              <para>
3172                This method is used to load an item from the database when the id of that item is known.
3173                Use the <methodname>DbControl.loadItem()</methodname> method to load the item. If the item
3174                is not found an <classname docapi="net.sf.basedb.core">ItemNotFoundException</classname> should
3175                be thrown.
3176              </para>
3177             
3178              <programlisting language="java">
3179<![CDATA[
3180/**
3181  Get an <code>AnyItem</code> item when you know the id.
3182 
3183  @param dc The <code>DbControl</code> which will be used for
3184    permission checking and database access.
3185  @param id The id of the item to load
3186  @return The <code>AnyItem</code> item
3187  @throws ItemNotFoundException If an item with the specified
3188    id is not found
3189  @throws PermissionDeniedException If the logged in user doesn't
3190    have read permission to the item
3191  @throws BaseException If there is another error
3192*/
3193public static AnyItem getById(DbControl dc, int id)
3194  throws ItemNotFoundException, PermissionDeniedException, BaseException
3195{
3196  AnyItem a = dc.loadItem(AnyItem.class, id);
3197  if (a == null) throw new ItemNotFoundException("AnyItem[id="+id+"]");
3198  return a;
3199}
3200]]>
3201</programlisting>
3202             
3203            </listitem>
3204          </varlistentry>
3205       
3206          <varlistentry>
3207            <term>getQuery()</term>
3208            <listitem>
3209              <para>
3210              See <xref linkend="core_ref.rules.itemclass.getquery" />.
3211              </para>
3212            </listitem>
3213          </varlistentry>
3214        </variablelist>
3215       
3216        <bridgehead>Constructors</bridgehead>
3217       
3218        <para>
3219          Each item class needs only one constructor, which takes an object of the corresponding
3220          data class as a parameter. The constructor should never be invoked directly. Use the
3221          <methodname>DbControl.newItem()</methodname> method.
3222        </para>
3223
3224        <programlisting language="java">
3225<![CDATA[
3226AnyItem(AnyData anyData)
3227{
3228  super(anyData);
3229}
3230]]>
3231</programlisting>
3232
3233        <bridgehead>Core methods</bridgehead>
3234       
3235        <variablelist>
3236          <varlistentry>
3237            <term>isUsed()</term>
3238            <listitem>
3239              <para>
3240                This method is defined by the <classname docapi="net.sf.basedb.core">BasicItem</classname> class and
3241                is called whenever we need to know if there are other items referencing the current item. The main
3242                use case is to let client applications know if it is safe to delete an object or not.
3243                The default implementation checks <classname docapi="net.sf.basedb.core">AnyToAny</classname> 
3244                links between items. A subclass must override this method if it can be referenced by other items.
3245                A subclass should always call <methodname>super.isUsed()</methodname> as a last check if it is not
3246                used by any other item. The method should check if it is beeing used (referenced by) some other item.
3247                For example, a <classname docapi="net.sf.basedb.core">Tag</classname> is used if there is an
3248                <classname docapi="net.sf.basedb.core">Extract</classname> with that tag. The simplest way to check
3249                if the item is used is to use a predefined query that counts the number of references.
3250              </para>
3251             
3252              <programlisting language="java">
3253<![CDATA[
3254/**
3255  Check if:
3256  <ul>
3257  <li>Some {@link Extract}:s are marked with this tag
3258  </ul>
3259*/
3260public boolean isUsed()
3261  throws BaseException
3262{
3263  org.hibernate.Session session = getDbControl().getHibernateSession();
3264  org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
3265    "GET_EXTRACTS_FOR_TAG", "count(*)");
3266  /*
3267    SELECT {1}
3268    FROM ExtractData ext
3269    WHERE ext.tag = :tag
3270  */
3271  query.setEntity("tag", this.getData());
3272  boolean used = HibernateUtil.loadData(Long.class, query) > 0;
3273  return used || super.isUsed();
3274}
3275]]>
3276</programlisting>
3277             
3278              <para>
3279                Sometimes it may be harder to decide what counts as using an item or not. Some examples:
3280              </para>
3281             
3282              <itemizedlist>
3283                <listitem>
3284                  <para>
3285                    An event for a sample does not count as using the sample, since they hava a
3286                    parent-child relationship. Ie. deleting the sample will also delete all events
3287                    associated with it. On the other hand, the protocol registered for the event counts
3288                    as using the protocol, because deleting the protocol should not delete all events.
3289                  </para>
3290                </listitem>
3291                <listitem>
3292                  <para>
3293                    As a general rule, if one item is used by a second item, then the second item cannot
3294                    be used by the first. It could lead to situations where it would be impossible to
3295                    delete either one of them.
3296                  </para>
3297                </listitem>
3298              </itemizedlist>
3299            </listitem>
3300          </varlistentry>
3301
3302          <varlistentry>
3303            <term>getUsingItems()</term>
3304            <listitem>
3305              <para>
3306                Find all items that are referencing this one. This method is related to the
3307                <methodname>isUsed()</methodname> method and is defined in the <classname docapi="net.sf.basedb.core">BasicItem</classname>
3308                class. The default implementation load all items linked via an <classname docapi="net.sf.basedb.core">AnyToAny</classname>
3309                link that has the <code>usingTo</code> flag set to true. A subclass must override this method if it can
3310                be referenced to be used by other items. A subclass should always call <methodname>super.getUsingItems()</methodname> 
3311                first and then add extra items to the Set returned by that call. For example, a <classname docapi="net.sf.basedb.core">Tag</classname>
3312                should load all <classname docapi="net.sf.basedb.core">Extract</classname>:s with that tag.
3313              </para>
3314              <programlisting language="java">
3315<![CDATA[
3316/**
3317  Get all:
3318  <ul>
3319  <li>{@link Extract}:s marked with this tag
3320  <ul>
3321*/
3322@Override
3323public Set<ItemProxy> getUsingItems()
3324{
3325  Set<ItemProxy> using = super.getUsingItems();
3326  org.hibernate.Session session = getDbControl().getHibernateSession();
3327   
3328  // Extracts
3329  org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
3330      "GET_EXTRACTS_FOR_TAG", "ext.id");
3331  /*
3332    SELECT {1}
3333    FROM ExtractData ext
3334    WHERE ext.tag = :tag
3335  */
3336  query.setEntity("tag", this.getData());
3337  addUsingItems(using, Item.EXTRACT, query);
3338  return using;
3339}
3340]]>
3341</programlisting>
3342            </listitem>
3343          </varlistentry>
3344         
3345          <varlistentry>
3346            <term>initPermissions(int, int)</term>
3347            <listitem>
3348              <para>
3349                See <xref linkend="core_ref.rules.itemclass.initpermissions" />.
3350              </para>
3351            </listitem>
3352          </varlistentry>
3353       
3354          <varlistentry>
3355            <term>validate() </term>
3356            <listitem>
3357              <para>
3358                See <xref linkend="core_ref.rules.itemclass.validation" />.
3359              </para>
3360            </listitem>
3361          </varlistentry>
3362       
3363          <varlistentry>
3364            <term>onBeforeCommit(Action)</term>
3365            <term>setProjectDefaults(Project)</term>
3366            <term>onAfterInsert()</term>
3367            <term>onAfterCommit(Action) </term>
3368            <term>onRollback(Action)</term>
3369            <listitem>
3370              <para>
3371                See <xref linkend="core_ref.rules.itemclass.transactions"/>.
3372              </para>
3373            </listitem>
3374          </varlistentry>
3375        </variablelist>
3376       
3377        <bridgehead>Getter and setter methods</bridgehead>
3378       
3379        <para>
3380          The get methods for basic property types are usually very simple. All that is needed is to
3381          return the value. Be aware of date values though, they are mutable and must be copied.
3382        </para>
3383         
3384        <programlisting language="java">
3385<![CDATA[
3386/**
3387   Get the value of the string property.
3388*/
3389public String getStringProperty()
3390{
3391   return getData().getStringProperty();
3392}
3393
3394/**
3395   Get the value of the int property.
3396*/
3397public int getIntProperty()
3398{
3399   return getData().getIntProperty();
3400}
3401
3402/**
3403   Get the value of the boolean property.
3404*/
3405public boolean isBooleanProperty()
3406{
3407   return getData().isBooleanProperty();
3408}
3409
3410/**
3411   Get the value of the date property.
3412   @return A date object or null if unknown
3413*/
3414public Date getDateProperty()
3415{
3416   return DateUtil.copy(getData().getDateProperty());
3417}
3418]]>
3419</programlisting>
3420
3421          <para>
3422            The set methods must always check for <constant>WRITE</constant> permission and validate
3423            the parameters. There are plenty of utility method to help with this.
3424          </para>
3425         
3426          <programlisting language="java">
3427<![CDATA[
3428/**
3429   The maximum length of the string property. Check the length
3430   agains this value before calling {@link #setStringProperty(String)}
3431   to avoid exceptions.
3432*/
3433public static final int MAX_STRINGPROPERTY_LENGTH =
3434   AnyData.MAX_STRINGPROPERTY_LENGTH;
3435
3436/**
3437   Set the value of the string property. Null values are not
3438   allowed and the length must be shorter than
3439   {@link #MAX_STRINGPROPERTY_LENGTH}.
3440   @param value The new value
3441   @throws PermissionDeniedException If the logged in user
3442      doesn't have write permission
3443   @throws InvalidDataException If the value is null or too long
3444*/
3445public void setStringProperty(String value)
3446   throws PermissionDeniedException, InvalidDataException
3447{
3448   checkPermission(Permission.WRITE);
3449   getData.setStringProperty(
3450      StringUtil.setNotNullString(value, "stringProperty", MAX_STRINGPROPERTY_LENGTH)
3451   );
3452}
3453
3454/**
3455   Set the value of the int property. The value mustn't be less than
3456   zero.
3457   @param value The new value
3458   @throws PermissionDeniedException If the logged in user
3459      doesn't have write permission
3460   @throws InvalidDataException If the value is less than zero
3461*/
3462
3463public void setIntProperty(int value)
3464   throws PermissionDeniedException, InvalidDataException
3465{
3466   checkPermission(Permission.WRITE);
3467   getData.setIntProperty(
3468      IntegerUtil.checkMin(value, "intProperty", 0)
3469   );
3470}
3471
3472/**
3473   Set the value of the boolean property.
3474   @param value The new value
3475   @throws PermissionDeniedException If the logged in user
3476      doesn't have write permission
3477*/
3478public void setBooleanProperty(boolean value)
3479   throws PermissionDeniedException
3480{
3481   checkPermission(Permission.WRITE);
3482   getData.setBooleanProperty(value);
3483}
3484
3485/**
3486   Set the value of the date property. Null values are allowed.
3487   @param value The new value
3488   @throws PermissionDeniedException If the logged in user
3489      doesn't have write permission
3490*/
3491public void setDateProperty(Date value)
3492   throws PermissionDeniedException
3493{
3494   checkPermission(Permission.WRITE);
3495   getData().setDateProperty(DateUtil.setNullableDate(value, "dateProperty"));
3496}
3497]]>
3498</programlisting>
3499
3500        <bridgehead>Many-to-one associations</bridgehead>
3501       
3502        <para>
3503          Many-to-one associations require sligthly more work. First of all, the item must be connected to a
3504          <classname docapi="net.sf.basedb.core">DbControl</classname> since it is used to load the information
3505          from the database and crete the new item object. Secondly, we must make sure to check for use
3506          permission on the referenced object in the setter method.
3507        </para>
3508       
3509        <programlisting language="java">
3510<![CDATA[
3511/**
3512   Get the associated other item.
3513   @return The OtherItem item
3514   @throws PermissionDeniedException If the logged in user
3515      doesn't have read permission
3516   @throws BaseException If there is another error
3517*/
3518public OtherItem getOtherItem()
3519   throws PermissionDeniedException, BaseException
3520{
3521   return getDbControl().getItem(OtherItem.class, getData().getOtherItem());
3522}
3523
3524/**
3525   Set the associated item. Null is not allowed.
3526   @param other The other item
3527   @throws PermissionDeniedException If the logged in user
3528      doesn't have write permission
3529   @throws InvalidDataException If the other item is null
3530   @throws BaseException If there is another error
3531*/
3532public void setOtherItem(OtherItem other)
3533   throws PermissionDeniedException, InvalidDataException, BaseException
3534{
3535   checkPermission(Permission.WRITE);
3536   if (otherItem == null) throw new InvalidUseOfNullException("otherItem");
3537   getData().setOtherItem(otherItem.getData());
3538}
3539]]>
3540</programlisting>
3541
3542        <bridgehead>One-to-many and many-to-many associations</bridgehead>
3543        <para>
3544          If the association is a one-to-many or many-to-many it becomes a little more complicated again.
3545          There are many types of such associations and how they are handled usually depends on if the
3546          are set:s, map:s, list:s or any other type of collections. In all cases we need methods for adding
3547          and removing items, and a method that returns a <interfacename docapi="net.sf.basedb.core.query">Query</interfacename>
3548          that can list all associated items. The first example if for parent/child relationship, which is a one-to-many
3549          association where the children are mapped as a set.
3550        </para>
3551       
3552        <programlisting language="java">
3553<![CDATA[
3554/**
3555   Create a child item for this any item.
3556   @return The new AChildItem object
3557   @throws PermissionDeniedException If the logged in user doesn't have
3558      write permission
3559   @throws BaseException If there is another error
3560*/
3561public AChildItem newChildItem()
3562   throws PermissionDeniedException, BaseException
3563{
3564   checkPermission(Permission.WRITE);
3565   return AChildItem.getNew(getDbControl(), this);
3566}
3567
3568/**
3569   Get a query that will return all child items for this any item.
3570   @return A {@link Query} object
3571*/
3572public ItemQuery<AChildItem> getChildItems()
3573{
3574  return AChildItem.getQuery(this);
3575}
3576]]>
3577</programlisting>
3578        <para>
3579          The second example is for the many-to-many associations between users and roles, which is also mapped as a set.
3580        </para>
3581        <programlisting language="java">
3582<![CDATA[
3583// Role.java
3584/**
3585   Add a user to this role.
3586   @param user The user to add
3587   @throws PermissionDeniedException If the logged in user doesn't
3588      have write permission for the role and
3589      use permission for the user
3590   @throws InvalidDataException If the user is null
3591*/
3592public void addUser(User user)
3593   throws PermissionDeniedException, InvalidDataException
3594{
3595   checkPermission(Permission.WRITE);
3596   if (user == null) throw new InvalidUseOfNullException("user");
3597   user.checkPermission(Permission.USE);
3598   getData().getUsers().add(user.getData());
3599}
3600
3601/**
3602   Remove a user from this role.
3603   @param user The user to remove
3604   @throws PermissionDeniedException If the logged in user doesn't
3605      have write permission for the role and
3606      use permission for the user
3607   @throws InvalidDataException If the user is null
3608*/
3609public void removeUser(User user)
3610   throws PermissionDeniedException, InvalidDataException
3611{
3612   checkPermission(Permission.WRITE);
3613   if (user == null) throw new InvalidUseOfNullException("user");
3614   user.checkPermission(Permission.USE);
3615   getData().getUsers().remove(user.getData());
3616}
3617
3618/**
3619   Check if the given user is member of this role or not.
3620   @param user The user to check
3621   @return TRUE if the user is member, FALSE otherwise
3622*/
3623public boolean isMember(User user)
3624{
3625   return getData().getUsers().contains(user.getData());
3626}
3627
3628/**
3629   Get a query that returns the users that
3630   are members of this role. This query excludes users that the logged
3631   in user doesn't have permission to read.
3632   @see User#getQuery()
3633*/
3634public ItemQuery<User> getUsers()
3635{
3636   ItemQuery<User> query = User.getQuery();
3637   query.joinPermanent(
3638      Hql.innerJoin("roles", Item.ROLE.getAlias())
3639   );
3640   query.restrictPermanent(
3641      Restrictions.eq(
3642         Hql.alias(Item.ROLE.getAlias()),
3643         Hql.entity(this)
3644      )
3645   );
3646   return query;
3647}
3648
3649// User.java
3650/**
3651   Get a query that returns the roles where this user is a
3652   member. The query excludes roles that the logged in user doesn't have
3653   permission to read.
3654   @see Role#getQuery()
3655*/
3656public ItemQuery<Role> getRoles()
3657{
3658   ItemQuery<Role> query = Role.getQuery();
3659   query.joinPermanent(
3660      Hql.innerJoin("users", Item.USER.getAlias())
3661   );
3662   query.restrictPermanent(
3663      Restrictions.eq(
3664         Hql.alias(Item.USER.getAlias()),
3665         Hql.entity(this)
3666      )
3667   );
3668   return query;
3669}
3670]]>
3671</programlisting>
3672        <para>
3673          Note that we have a query method in both classes, but the association can only be changed from the
3674          <classname docapi="net.sf.based.core">Role</classname>. We recommend that modifier methods are put
3675          in one of the classes only. The last example is the many-to-many relation between projects and users
3676          which is a map to the permission for the user in the project.
3677        </para>
3678       
3679        <programlisting language="java">
3680<![CDATA[
3681// Project.java
3682/**
3683   Grant a user permissions to this project. Use an empty set
3684   or null to remove the user from this project.
3685
3686   @param user The user
3687   @param permissions The permissions to grant, or null to revoke all permissions
3688   @throws PermissionDeniedException If the logged in user doesn't have
3689      write permission for the project
3690   @throws InvalidDataException If the user is null
3691   @see Permission
3692*/
3693public void setPermissions(User user, Set<Permission> permissions)
3694   throws PermissionDeniedException, InvalidDataException
3695{
3696   checkPermission(Permission.WRITE);
3697   if (user == null) throw new InvalidUseOfNullException("user");
3698   if (permissions == null || permissions.isEmpty())
3699   {
3700      getData().getUsers().remove(user.getData());
3701   }
3702   else
3703   {
3704      getData().getUsers().put(user.getData(), Permission.grant(permissions));
3705   }
3706}
3707
3708/**
3709   Get the permissions for a user in this project.
3710   @param user The user for which we want to get the permission
3711   @return A set containing the granted permissions, or an
3712      empty set if no permissions have been granted
3713   @throws InvalidDataException If the user is null
3714   @see Permission
3715*/
3716public Set<Permission> getPermissions(User user)
3717   throws InvalidDataException
3718{
3719   if (user == null) throw new InvalidUseOfNullException("user");
3720   return Permission.fromInt(getData().getUsers().get(user.getData()));
3721}
3722
3723/**
3724   Get a query that returns the users that
3725   are members of this project. This query excludes users that the logged
3726   in user doesn't have permission to read.
3727   @see User#getQuery()
3728*/
3729public ItemQuery<User> getUsers()
3730{
3731   ItemQuery<User> query = User.getQuery();
3732   query.joinPermanent(
3733      Hql.innerJoin("projects", Item.PROJECT.getAlias())
3734   );
3735   query.restrictPermanent(
3736      Restrictions.eq(
3737         Hql.alias(Item.PROJECT.getAlias()),
3738         Hql.entity(this)
3739      )
3740   );
3741   return query;
3742}
3743
3744// User.java
3745/**
3746   Get a query that returns the projects where this user is a
3747   member. The query excludes projects that the logged in user doesn't have
3748   permission to read. The query doesn't include projects where this user is
3749   the owner.
3750   @see Project#getQuery()
3751*/
3752public ItemQuery<Project> getProjects()
3753{
3754   ItemQuery<Project> query = Project.getQuery();
3755   query.joinPermanent(
3756      Hql.innerJoin("users", Item.USER.getAlias())
3757   );
3758   query.restrictPermanent(
3759      Restrictions.eq(
3760         Hql.index(Item.USER.getAlias(), null),
3761         Hql.entity(this)
3762      )
3763   );
3764   return query;
3765}
3766]]>
3767</programlisting>
3768        <para>
3769          As you can see from these examples, the code is very different depending on the type of
3770          association. We don't give any more examples here, but if you are unsure you should look
3771          in the source code to get more inspiration.
3772        </para>
3773      </sect3>
3774    </sect2>   
3775
3776    <sect2 id="core_ref.rules.batchclass">
3777      <title>Batch-class rules</title>
3778      <para>
3779        TODO
3780      </para>
3781    </sect2>
3782   
3783    <sect2 id="core_ref.rules.testclass">
3784      <title>Test-class rules</title>
3785      <para>
3786        TODO
3787      </para>
3788    </sect2>
3789  </sect1>
3790 
3791  <sect1 id="core_ref.coreinternals">
3792    <title>Internals of the Core API</title>
3793    <para>
3794      This documentation is only available in the old format.
3795      See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html"
3796        >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html</ulink>
3797    </para>
3798    <sect2 id="core_ref.authentication">
3799      <title>Authentication and sessions</title>
3800      <para>
3801        This documentation is only available in the old format.
3802        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html"
3803          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html</ulink>
3804      </para>
3805    </sect2>   
3806    <sect2 id="core_ref.accesspermissions">
3807      <title>Access permissions</title>
3808      <para>
3809        This documentation is only available in the old format.
3810        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html"
3811          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html</ulink>
3812      </para>
3813    </sect2>   
3814    <sect2 id="core_ref.datavalidation">
3815      <title>Data validation</title>
3816      <para>
3817        TODO
3818      </para>
3819    </sect2>   
3820    <sect2 id="core_ref.transactions">
3821      <title>Transaction handling</title>
3822      <para>
3823        TODO
3824      </para>
3825    </sect2>   
3826    <sect2 id="core_ref.crwd">
3827      <title>Create/read/write/delete operations</title>
3828      <para>
3829        This documentation is only available in the old format.
3830        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html"
3831          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html</ulink>
3832      </para>
3833    </sect2>   
3834    <sect2 id="core_ref.batch">
3835      <title>Batch operations</title>
3836      <para>
3837        This documentation is only available in the old format.
3838        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html"
3839          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html</ulink>
3840      </para>
3841    </sect2>   
3842    <sect2 id="core_ref.quota">
3843      <title>Quota</title>
3844      <para>
3845        TODO
3846      </para>
3847    </sect2>   
3848    <sect2 id="core_ref.pluginexecution">
3849      <title>Plugin execution / job queue</title>
3850      <para>
3851        This documentation is only available in the old format.
3852        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html"
3853          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html</ulink>
3854      </para>
3855    </sect2>   
3856  </sect1>
3857
3858</chapter>
Note: See TracBrowser for help on using the repository browser.