Coverage Report - org.melati.poem.Table
 
Classes in this File Line Coverage Branch Coverage Complexity
Table
N/A
N/A
1
 
 1  
 /*
 2  
  * $Source$
 3  
  * $Revision$
 4  
  *
 5  
  * Copyright (C) 2000 William Chesters
 6  
  * 
 7  
  * Part of Melati (http://melati.org), a framework for the rapid
 8  
  * development of clean, maintainable web applications.
 9  
  *
 10  
  * Melati is free software; Permission is granted to copy, distribute
 11  
  * and/or modify this software under the terms either:
 12  
  *
 13  
  * a) the GNU General Public License as published by the Free Software
 14  
  *    Foundation; either version 2 of the License, or (at your option)
 15  
  *    any later version,
 16  
  *
 17  
  *    or
 18  
  *
 19  
  * b) any version of the Melati Software License, as published
 20  
  *    at http://melati.org
 21  
  *
 22  
  * You should have received a copy of the GNU General Public License and
 23  
  * the Melati Software License along with this program;
 24  
  * if not, write to the Free Software Foundation, Inc.,
 25  
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
 26  
  * GNU General Public License and visit http://melati.org to obtain the
 27  
  * Melati Software License.
 28  
  *
 29  
  * Feel free to contact the Developers of Melati (http://melati.org),
 30  
  * if you would like to work out a different arrangement than the options
 31  
  * outlined here.  It is our intention to allow Melati to be used by as
 32  
  * wide an audience as possible.
 33  
  *
 34  
  * This program is distributed in the hope that it will be useful,
 35  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 36  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 37  
  * GNU General Public License for more details.
 38  
  *
 39  
  * Contact details for copyright holder:
 40  
  *
 41  
  *     William Chesters <williamc At paneris.org>
 42  
  *     http://paneris.org/~williamc
 43  
  *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
 44  
  */
 45  
 
 46  
 package org.melati.poem;
 47  
 
 48  
 import org.melati.poem.util.Cache;
 49  
 
 50  
 import java.util.Enumeration;
 51  
 import java.util.List;
 52  
 import java.io.PrintStream;
 53  
 import java.sql.ResultSet;
 54  
 import java.sql.SQLException;
 55  
 
 56  
 /**
 57  
  * A table.
 58  
  *
 59  
  * @since 14-Apr-2008
 60  
  */
 61  
 public interface Table<P extends Persistent>  {
 62  
     /**
 63  
      * The database to which the table is attached.
 64  
      * @return the db
 65  
      */
 66  
     Database getDatabase();
 67  
 
 68  
     /**
 69  
      * Initialise the table.
 70  
      */
 71  
     void init();
 72  
     /**
 73  
      * Do stuff immediately after table initialisation.
 74  
      * <p>
 75  
      * This base method clears the column info caches and adds a listener
 76  
      * to the column info table to maintain the caches.
 77  
      * <p>
 78  
      * It may be overridden to perform other actions. For example to
 79  
      * ensure required rows exist in tables that define numeric ID's for
 80  
      * codes.
 81  
      *
 82  
      * @see #notifyColumnInfo(ColumnInfo)
 83  
      * @see #clearColumnInfoCaches()
 84  
      */
 85  
     void postInitialise();
 86  
     
 87  
     /**
 88  
      * Create the (possibly overridden) TableInfo if it has not yet been created.
 89  
      */
 90  
     void createTableInfo();
 91  
     /**
 92  
      * The table's programmatic name.  Identical with its name in the DSD (if the
 93  
      * table was defined there) and in its <TT>tableinfo</TT> entry.
 94  
      * This will normally be the same as the name in the RDBMS itself, however that name
 95  
      * may be translated to avoid DBMS specific name clashes.
 96  
      *
 97  
      * @return the table name, case as defined in the DSD
 98  
      * @see org.melati.poem.dbms.Dbms#melatiName(String)
 99  
      */
 100  
     String getName();
 101  
 
 102  
     /**
 103  
      * @return table name quoted using the DBMS' specific quoting rules.
 104  
      */
 105  
     String quotedName();
 106  
 
 107  
     /**
 108  
      * The human-readable name of the table.  POEM itself doesn't use this, but
 109  
      * it's available to applications and Melati's generic admin system as a
 110  
      * default label for the table and caption for its records.
 111  
       * @return The human-readable name of the table
 112  
       */
 113  
     String getDisplayName();
 114  
 
 115  
     /**
 116  
      * A brief description of the table's function.  POEM itself doesn't use
 117  
      * this, but it's available to applications and Melati's generic admin system
 118  
      * as a default label for the table and caption for its records.
 119  
      * @return the brief description
 120  
      */
 121  
     String getDescription();
 122  
 
 123  
     /**
 124  
      * The category of this table.  POEM itself doesn't use
 125  
      * this, but it's available to applications and Melati's generic admin system
 126  
      * as a default label for the table and caption for its records.
 127  
      *
 128  
      * @return the category
 129  
      */
 130  
     TableCategory getCategory();
 131  
 
 132  
     /**
 133  
      * @return the {@link org.melati.poem.TableInfo} for this table
 134  
      */
 135  
     TableInfo getInfo();
 136  
 
 137  
     /**
 138  
      * The troid (<TT>id</TT>) of the table's entry in the <TT>tableinfo</TT>
 139  
      * table.  It will always have one (except during initialisation, which the
 140  
      * application programmer will never see).
 141  
      *
 142  
      * @return id in TableInfo metadata table
 143  
      */
 144  
     Integer tableInfoID();
 145  
 
 146  
     /**
 147  
      * The table's column with a given name.  If the table is defined in the DSD
 148  
      * under the name <TT><I>foo</I></TT>, there will be an
 149  
      * application-specialised <TT>Table</TT> subclass, called
 150  
      * <TT><I>Foo</I>Table</TT> (and available as <TT>get<I>Foo</I>Table</TT>
 151  
      * from the application-specialised <TT>Database</TT> subclass) which has
 152  
      * extra named methods for accessing the table's predefined <TT>Column</TT>s.
 153  
      *
 154  
      * @param nameP name of column to get
 155  
      * @return column of that name
 156  
      * @throws org.melati.poem.NoSuchColumnPoemException if there is no column with that name
 157  
      */
 158  
     Column<?> getColumn(String nameP) throws NoSuchColumnPoemException;
 159  
 
 160  
     /**
 161  
      * All the table's columns.
 162  
      *
 163  
      * @return an <TT>Enumeration</TT> of <TT>Column</TT>s
 164  
      * @see org.melati.poem.Column
 165  
      */
 166  
     Enumeration<Column<?>> columns();
 167  
 
 168  
     /**
 169  
      * A list of all the table's columns.
 170  
      */
 171  
     List<Column<?>> getColumns(); 
 172  
     
 173  
     /**
 174  
      * @return the number of columns in this table.
 175  
      */
 176  
     int getColumnsCount();
 177  
 
 178  
     /**
 179  
      * @param columnInfoID the Id for the Column table
 180  
      * @return the Column with a TROID equal to columnInfoID
 181  
      */
 182  
     Column<?> columnWithColumnInfoID(int columnInfoID);
 183  
 
 184  
     /**
 185  
      * The table's troid column.  Every table in a POEM database must have a
 186  
      * troid (table row ID, or table-unique non-nullable integer primary key),
 187  
      * often but not necessarily called <TT>id</TT>, so that it can be
 188  
      * conveniently `named'.
 189  
      *
 190  
      * @return the id column
 191  
      * @see #getObject(Integer)
 192  
      */
 193  
     Column<Integer> troidColumn();
 194  
 
 195  
     /**
 196  
      * @return The table's deleted-flag column, if any.
 197  
      */
 198  
     Column<Boolean> deletedColumn();
 199  
 
 200  
     /**
 201  
      * The table's primary display column, the Troid column if not set.
 202  
      * This is the column used to represent records from the table
 203  
      * concisely in reports or whatever.  It is determined
 204  
      * at initialisation time by examining the <TT>Column</TT>s
 205  
      * <TT>getPrimaryDisplay()</TT> flags.
 206  
      *
 207  
      * @return the table's display column, or <TT>null</TT> if it hasn't got one
 208  
      *
 209  
      * see Column#setColumnInfo
 210  
      * @see org.melati.poem.ReferencePoemType#_stringOfCooked
 211  
      * @see org.melati.poem.DisplayLevel#primary
 212  
      */
 213  
     Column<?> displayColumn();
 214  
 
 215  
     /**
 216  
      * @param column the display column to set
 217  
      */
 218  
     void setDisplayColumn(Column<?> column);
 219  
 
 220  
     /**
 221  
      * In a similar manner to the primary display column, each table can have
 222  
      * one primary criterion column.
 223  
      * <p>
 224  
      * The Primary Criterion is the main grouping field of the table,
 225  
      * ie the most important non-unique type field.
 226  
      * <p>
 227  
      * For example the Primary Criterion for a User table might be Nationality.
 228  
      *
 229  
      * @return the search column, if any
 230  
      * @see org.melati.poem.Searchability
 231  
      */
 232  
     Column<?> primaryCriterionColumn();
 233  
 
 234  
     /**
 235  
      * @param column the search column to set
 236  
      */
 237  
     void setSearchColumn(Column<?> column);
 238  
 
 239  
     /**
 240  
      * If the troidColumn has yet to be set then returns an empty string.
 241  
      *
 242  
      * @return comma separated list of the columns to order by
 243  
      */
 244  
     String defaultOrderByClause();
 245  
 
 246  
     /**
 247  
      * Clear caches.
 248  
      */
 249  
     void clearColumnInfoCaches();
 250  
 
 251  
     /**
 252  
      * Clears columnInfo caches, normally a no-op.
 253  
      *
 254  
      * @param infoP the possibly null ColumnInfo meta-data persistent
 255  
      */
 256  
     void notifyColumnInfo(ColumnInfo infoP);
 257  
 
 258  
     /**
 259  
      * Return columns at a display level in display order.
 260  
      *
 261  
      * @param level the {@link org.melati.poem.DisplayLevel} to select
 262  
      * @return an Enumeration of columns at the given level
 263  
      */
 264  
     Enumeration<Column<?>> displayColumns(DisplayLevel level);
 265  
 
 266  
     /**
 267  
      * @param level the {@link org.melati.poem.DisplayLevel} to select
 268  
      * @return the number of columns at a display level.
 269  
      */
 270  
     int displayColumnsCount(DisplayLevel level);
 271  
 
 272  
     /**
 273  
      * The table's columns for detailed display in display order.
 274  
      *
 275  
      * @return an <TT>Enumeration</TT> of <TT>Column</TT>s
 276  
      * @see org.melati.poem.Column
 277  
      * @see #displayColumns(org.melati.poem.DisplayLevel)
 278  
      * @see org.melati.poem.DisplayLevel#detail
 279  
      */
 280  
     Enumeration<Column<?>> getDetailDisplayColumns();
 281  
 
 282  
     /**
 283  
      * @return the number of columns at display level <tt>Detail</tt>
 284  
      */
 285  
     int getDetailDisplayColumnsCount();
 286  
 
 287  
     /**
 288  
      * The table's columns designated for display in a record, in display order.
 289  
      *
 290  
      * @return an <TT>Enumeration</TT> of <TT>Column</TT>s
 291  
      * @see org.melati.poem.Column
 292  
      * @see #displayColumns(org.melati.poem.DisplayLevel)
 293  
      * @see org.melati.poem.DisplayLevel#record
 294  
      */
 295  
     Enumeration<Column<?>> getRecordDisplayColumns();
 296  
 
 297  
     /**
 298  
      * @return the number of columns at display level <tt>Record</tt>
 299  
      */
 300  
     int getRecordDisplayColumnsCount();
 301  
 
 302  
     /**
 303  
      * The table's columns designated for display in a record summary, in display
 304  
      * order.
 305  
      *
 306  
      * @return an <TT>Enumeration</TT> of <TT>Column</TT>s
 307  
      * @see org.melati.poem.Column
 308  
      * @see #displayColumns(org.melati.poem.DisplayLevel)
 309  
      * @see org.melati.poem.DisplayLevel#summary
 310  
      */
 311  
     Enumeration<Column<?>> getSummaryDisplayColumns();
 312  
 
 313  
     /**
 314  
      * @return the number of columns at display level <tt>Summary</tt>
 315  
      */
 316  
     int getSummaryDisplayColumnsCount();
 317  
 
 318  
     /**
 319  
      * The table's columns designated for use as search criteria, in display
 320  
      * order.
 321  
      *
 322  
      * @return an <TT>Enumeration</TT> of <TT>Column</TT>s
 323  
      * @see org.melati.poem.Column
 324  
      */
 325  
     Enumeration<Column<?>> getSearchCriterionColumns();
 326  
 
 327  
     /**
 328  
      * @return the number of columns which are searchable
 329  
      */
 330  
     int getSearchCriterionColumnsCount();
 331  
 
 332  
     /**
 333  
      * Use this for DDL statements, ie those which alter the structure of the db.
 334  
      * Postgresql in particular does not like DDL statements being executed within a transaction.
 335  
      *
 336  
      * @param sql the SQL DDL statement to execute
 337  
      * @throws org.melati.poem.StructuralModificationFailedPoemException
 338  
      */
 339  
     void dbModifyStructure(String sql)
 340  
         throws StructuralModificationFailedPoemException;
 341  
 
 342  
     /**
 343  
      * Constraints are not used in POEM, but you might want to use them if
 344  
      * exporting the db or using schema visualisation tools.
 345  
      */
 346  
     void dbAddConstraints();
 347  
 
 348  
     /**
 349  
      * When deleting a table and used in tests.
 350  
      */
 351  
     void invalidateTransactionStuffs();
 352  
 
 353  
     /**
 354  
      * @param transaction possibly null if working with the committed transaction
 355  
      * @param persistent the Persistent to load
 356  
      */
 357  
     void load(PoemTransaction transaction, Persistent persistent);
 358  
 
 359  
     /**
 360  
      * The Transaction cannot be null, as this is trapped in
 361  
      * #deleteLock(SessionToken).
 362  
      * @param troid id of row to delete
 363  
      * @param transaction a non-null transaction
 364  
      */
 365  
     void delete(Integer troid, PoemTransaction transaction);
 366  
 
 367  
     /**
 368  
      * @param transaction our PoemTransaction
 369  
      * @param p the Persistent to write
 370  
      */
 371  
     void writeDown(PoemTransaction transaction, Persistent p);
 372  
 
 373  
     /**
 374  
      * Invalidate table cache.
 375  
      *
 376  
      * NOTE Invalidated cache elements are reloaded when next read
 377  
      */
 378  
     void uncache();
 379  
 
 380  
     /**
 381  
      * @param maxSize new maximum size
 382  
      */
 383  
     void trimCache(int maxSize);
 384  
 
 385  
     /**
 386  
      * @return the Cache Info object
 387  
      */
 388  
     Cache.Info getCacheInfo();
 389  
 
 390  
     /**
 391  
      * Add a {@link org.melati.poem.TableListener} to this Table.
 392  
      */
 393  
     void addListener(TableListener listener);
 394  
 
 395  
     /**
 396  
      * Notify the table that one if its records is about to be changed in a
 397  
      * transaction.  You can (with care) use this to support cacheing of
 398  
      * frequently-used facts about the table's records.
 399  
      *
 400  
      * @param transaction the transaction in which the change will be made
 401  
      * @param persistent  the record to be changed
 402  
      */
 403  
     void notifyTouched(PoemTransaction transaction, Persistent persistent);
 404  
 
 405  
     /**
 406  
      * @return the Transaction serial
 407  
      */
 408  
     long serial(PoemTransaction transaction);
 409  
 
 410  
     /**
 411  
      * Lock this record.
 412  
      */
 413  
     void readLock();
 414  
 
 415  
     /**
 416  
      * The object from the table with a given troid.
 417  
      *
 418  
      * @param troid       Every record (object) in a POEM database must have a
 419  
      *                    troid (table row ID, or table-unique non-nullable
 420  
      *                    integer primary key), often but not necessarily called
 421  
      *                    <TT>id</TT>, so that it can be conveniently `named' for
 422  
      *                    retrieval by this method.
 423  
      *
 424  
      * @return A <TT>Persistent</TT> of the record with the given troid;
 425  
      *         or, if the table was defined in the DSD under the name
 426  
      *         <TT><I>foo</I></TT>, an application-specialised subclass
 427  
      *         <TT><I>Foo</I></TT> of <TT>Persistent</TT>.  In that case, there
 428  
      *         will also be an application-specialised <TT>Table</TT> subclass,
 429  
      *         called <TT><I>Foo</I>Table</TT> (and available as
 430  
      *         <TT>get<I>Foo</I>Table</TT> from the application-specialised
 431  
      *         <TT>Database</TT> subclass), which has a matching method
 432  
      *         <TT>get<I>Foo</I>Object</TT> for obtaining the specialised object
 433  
      *         under its own type.  Note that no access checks are done at this
 434  
      *         stage: you may not be able to do anything with the object handle
 435  
      *         returned from this method without provoking a
 436  
      *         <TT>PoemAccessException</TT>.
 437  
      *
 438  
      * @exception org.melati.poem.NoSuchRowPoemException
 439  
      *                if there is no row in the table with the given troid
 440  
      *
 441  
      * @see org.melati.poem.Persistent#getTroid()
 442  
      */
 443  
     P getObject(Integer troid) throws NoSuchRowPoemException;
 444  
 
 445  
     /**
 446  
      * The object from the table with a given troid.  See previous.
 447  
      *
 448  
      * @param troid the table row id
 449  
      * @return the Persistent
 450  
      * @throws org.melati.poem.NoSuchRowPoemException if not found
 451  
      * @see #getObject(Integer)
 452  
      */
 453  
     Persistent getObject(int troid) throws NoSuchRowPoemException;
 454  
 
 455  
     /**
 456  
      * The from clause has been added as an argument because it is
 457  
      * inextricably linked to the when clause, but the default is
 458  
      * {@link #quotedName()}.
 459  
      *
 460  
      * It is the programmer's responsibility to ensure that the where clause
 461  
      * is suitable for the target DBMS.
 462  
      *
 463  
      * @param fromClause Comma separated list of table names or null for default.
 464  
      * @param whereClause SQL fragment
 465  
      * @param orderByClause Comma separated list
 466  
      * @param includeDeleted Flag as to whether to include soft deleted records
 467  
      * @param excludeUnselectable Whether to append unselectable exclusion SQL
 468  
      * TODO Should work within some kind of limit
 469  
      * @return an SQL SELECT statement put together from the arguments and
 470  
      * default order by clause.
 471  
      */
 472  
     String selectionSQL(String fromClause, String whereClause,
 473  
                                String orderByClause, boolean includeDeleted,
 474  
                                boolean excludeUnselectable);
 475  
 
 476  
     /**
 477  
      * It is the programmer's responsibility to ensure that the where clause
 478  
      * is suitable for the target DBMS.
 479  
      *
 480  
      * @return an {@link java.util.Enumeration} of Troids satisfying the criteria.
 481  
      */
 482  
     Enumeration<Integer> troidSelection(String whereClause, String orderByClause,
 483  
                                       boolean includeDeleted,
 484  
                                       PoemTransaction transaction);
 485  
 
 486  
     /**
 487  
      *
 488  
      * @see #troidSelection(String, String, boolean, org.melati.poem.PoemTransaction)
 489  
      * @param criteria Represents selection criteria possibly on joined tables
 490  
      * @param transaction A transaction or null for
 491  
      *                    {@link org.melati.poem.PoemThread#transaction()}
 492  
      * @return a selection of troids given arguments specifying a query
 493  
      */
 494  
     Enumeration<Integer> troidSelection(Persistent criteria, String orderByClause,
 495  
                                       boolean includeDeleted,
 496  
                                       boolean excludeUnselectable,
 497  
                                       PoemTransaction transaction);
 498  
 
 499  
     /**
 500  
      * @param flag whether to remember or forget
 501  
      */
 502  
     void rememberAllTroids(boolean flag);
 503  
 
 504  
     /**
 505  
      * @param limit the limit to set
 506  
      */
 507  
     void setCacheLimit(Integer limit);
 508  
 
 509  
     /**
 510  
      * A <TT>SELECT</TT>ion of troids of objects from the table meeting given
 511  
      * criteria.
 512  
      *
 513  
      * It is the programmer's responsibility to ensure that the where clause
 514  
      * is suitable for the target DBMS.
 515  
      *
 516  
      * If the orderByClause is null, then the default order by clause is applied.
 517  
      * If the orderByClause is an empty string, ie "", then no ordering is
 518  
      * applied.
 519  
      *
 520  
      * @param whereClause an SQL snippet
 521  
      * @param orderByClause an SQL snippet
 522  
      * @param includeDeleted whether to include deleted records, if any
 523  
      *
 524  
      * @return an <TT>Enumeration</TT> of <TT>Integer</TT>s, which can be mapped
 525  
      *         onto <TT>Persistent</TT> objects using <TT>getObject</TT>;
 526  
      *         or you can just use <TT>selection</TT>
 527  
      *
 528  
      * @see #getObject(Integer)
 529  
      * @see #selection(String, String, boolean)
 530  
      */
 531  
     Enumeration<Integer> troidSelection(String whereClause, String orderByClause,
 532  
                                       boolean includeDeleted)
 533  
         throws SQLPoemException;
 534  
 
 535  
     /**
 536  
      * All the objects in the table.
 537  
      *
 538  
      * @return An <TT>Enumeration</TT> of <TT>Persistent</TT>s, or, if the table
 539  
      *         was defined in the DSD under the name <TT><I>foo</I></TT>, of
 540  
      *         application-specialised subclasses <TT><I>Foo</I></TT>.  Note
 541  
      *         that no access checks are done at this stage: you may not be able
 542  
      *         to do anything with some of the object handles in the enumeration
 543  
      *         without provoking a <TT>PoemAccessException</TT>.  If the table
 544  
      *         has a <TT>deleted</TT> column, the objects flagged as deleted will
 545  
      *         be passed over.
 546  
      * @see Selectable#selection()
 547  
      */
 548  
     Enumeration<P> selection() throws SQLPoemException;
 549  
 
 550  
     /**
 551  
      * A <TT>SELECT</TT>ion of objects from the table meeting given criteria.
 552  
      * This is one way to run a search against the database and return the
 553  
      * results as a series of typed POEM objects.
 554  
      *
 555  
      * It is the programmer's responsibility to ensure that the where clause
 556  
      * is suitable for the target DBMS.
 557  
      *
 558  
      * @param whereClause         SQL <TT>SELECT</TT>ion criteria for the search:
 559  
      *                            the part that should appear after the
 560  
      *                            <TT>WHERE</TT> keyword
 561  
      *
 562  
      * @return An <TT>Enumeration</TT> of <TT>Persistent</TT>s, or, if the table
 563  
      *         was defined in the DSD under the name <TT><I>foo</I></TT>, of
 564  
      *         application-specialised subclasses <TT><I>Foo</I></TT>.  Note
 565  
      *         that no access checks are done at this stage: you may not be able
 566  
      *         to do anything with some of the object handles in the enumeration
 567  
      *         without provoking a <TT>PoemAccessException</TT>.  If the table
 568  
      *         has a <TT>deleted</TT> column, the objects flagged as deleted will
 569  
      *         be passed over.
 570  
      *
 571  
      * @see org.melati.poem.Column#selectionWhereEq(Object)
 572  
      */
 573  
     Enumeration<P> selection(String whereClause)
 574  
         throws SQLPoemException;
 575  
 
 576  
     /**
 577  
      * Get an object satisfying the where clause.
 578  
      * It is the programmer's responsibility to use this in a
 579  
      * context where only one result will be found, if more than one
 580  
      * actually exist only the first will be returned.
 581  
      *
 582  
      * It is the programmer's responsibility to ensure that the where clause
 583  
      * is suitable for the target DBMS.
 584  
      *
 585  
      * @param whereClause         SQL <TT>SELECT</TT>ion criteria for the search:
 586  
      *                            the part that should appear after the
 587  
      *                            <TT>WHERE</TT> keyword
 588  
      * @return the first item satisfying criteria
 589  
      */
 590  
     Persistent firstSelection(String whereClause);
 591  
 
 592  
     /**
 593  
      * A <TT>SELECT</TT>ion of objects from the table meeting given criteria,
 594  
      * possibly including those flagged as deleted.
 595  
      *
 596  
      * If the orderByClause is null, then the default order by clause is applied.
 597  
      * If the orderByClause is an empty string, ie "", then no ordering is
 598  
      * applied.
 599  
      *
 600  
      * It is the programmer's responsibility to ensure that the where clause
 601  
      * is suitable for the target DBMS.
 602  
      *
 603  
      * @param includeDeleted      whether to return objects flagged as deleted
 604  
      *                            (ignored if the table doesn't have a
 605  
      *                            <TT>deleted</TT> column)
 606  
      * @return a ResultSet as an Enumeration
 607  
      * @see #selection(String)
 608  
      */
 609  
     Enumeration<P> selection(String whereClause, String orderByClause,
 610  
                                   boolean includeDeleted)
 611  
         throws SQLPoemException;
 612  
 
 613  
     /**
 614  
      * Return a selection of rows given an exemplar.
 615  
      *
 616  
      * @param criteria Represents selection criteria possibly on joined tables
 617  
      * @return an enumeration of like objects
 618  
      * @see #selection(String, String, boolean)
 619  
      */
 620  
     Enumeration<P> selection(Persistent criteria)
 621  
         throws SQLPoemException;
 622  
 
 623  
     /**
 624  
      * Return a selection of rows given arguments specifying a query.
 625  
      *
 626  
      * @see #selection(String, String, boolean)
 627  
      * @param criteria Represents selection criteria possibly on joined tables
 628  
      * @param orderByClause Comma separated list
 629  
      * @return an enumeration of like objects with the specified ordering
 630  
      */
 631  
     Enumeration<P> selection(Persistent criteria, String orderByClause)
 632  
         throws SQLPoemException;
 633  
 
 634  
     /**
 635  
      * Return a selection of rows given arguments specifying a query.
 636  
      *
 637  
      * @see #selection(String, String, boolean)
 638  
      * @param criteria Represents selection criteria possibly on joined tables
 639  
      * @param orderByClause Comma separated list
 640  
      * @param excludeUnselectable Whether to append unselectable exclusion SQL
 641  
      * @return an enumeration of like Persistents
 642  
      */
 643  
     Enumeration<P> selection(Persistent criteria, String orderByClause,
 644  
                                   boolean includeDeleted, boolean excludeUnselectable)
 645  
         throws SQLPoemException;
 646  
 
 647  
 
 648  
     /**
 649  
      * @param whereClause the SQL fragment to count the results of
 650  
      * @return the SQL string for the current SQL dialect
 651  
      */
 652  
     String countSQL(String whereClause);
 653  
 
 654  
     /**
 655  
      * Return an SQL statement to count rows put together from the arguments.
 656  
      *
 657  
      * It is the programmer's responsibility to ensure that the where clause
 658  
      * is suitable for the target DBMS.
 659  
      *
 660  
      * @param fromClause Comma separated list of table names
 661  
      * @return the SQL query
 662  
      */
 663  
     String countSQL(String fromClause, String whereClause,
 664  
                            boolean includeDeleted, boolean excludeUnselectable);
 665  
 
 666  
     /**
 667  
      * It is the programmer's responsibility to ensure that the where clause
 668  
      * is suitable for the target DBMS.
 669  
      *
 670  
      * @return the number records satisfying criteria.
 671  
      */
 672  
     int count(String whereClause,
 673  
                      boolean includeDeleted, boolean excludeUnselectable)
 674  
         throws SQLPoemException;
 675  
 
 676  
     /**
 677  
      * It is the programmer's responsibility to ensure that the where clause
 678  
      * is suitable for the target DBMS.
 679  
      *
 680  
      * @return the number records satisfying criteria.
 681  
      */
 682  
     int count(String whereClause, boolean includeDeleted)
 683  
         throws SQLPoemException;
 684  
 
 685  
     /**
 686  
      * It is the programmer's responsibility to ensure that the where clause
 687  
      * is suitable for the target DBMS.
 688  
      *
 689  
      * @return the number of records satisfying criteria.
 690  
      */
 691  
     int count(String whereClause)
 692  
         throws SQLPoemException;
 693  
 
 694  
     /**
 695  
      * @return the number of records in this table.
 696  
      */
 697  
     int count()
 698  
         throws SQLPoemException;
 699  
 
 700  
     /**
 701  
      * It is the programmer's responsibility to ensure that the where clause
 702  
      * is suitable for the target DBMS.
 703  
      *
 704  
      * @param whereClause the SQL criteria
 705  
      * @return whether any  records satisfy criteria.
 706  
      */
 707  
     boolean exists(String whereClause) throws SQLPoemException;
 708  
 
 709  
     /**
 710  
      * @param persistent a {@link org.melati.poem.Persistent} with some fields filled in
 711  
      * @return whether any  records exist with the same fields filled
 712  
      */
 713  
     boolean exists(Persistent persistent);
 714  
 
 715  
     /**
 716  
      * Append an SQL logical expression to the given buffer to match rows
 717  
      * according to criteria represented by the given object.
 718  
      * <p>
 719  
      * This default selects rows for which the non-null fields in the
 720  
      * given object match, but subtypes may add other criteria.
 721  
      * <p>
 722  
      * The column names are now qualified with the table name so that
 723  
      * subtypes can append elements of a join but there is no filtering
 724  
      * by canselect columns.
 725  
      *
 726  
      * TODO Add mechanism for searching for Nulls (that would be query
 727  
      * constructs as per SQL parse tree, but efferent not afferent)
 728  
      *
 729  
      * @see #notifyColumnInfo(org.melati.poem.ColumnInfo)
 730  
      * @see #clearColumnInfoCaches()
 731  
      */
 732  
     void appendWhereClause(StringBuffer clause, Persistent persistent);
 733  
 
 734  
     /**
 735  
      * Return an SQL WHERE clause to select rows that match the non-null
 736  
      * fields of the given object.
 737  
      * <p>
 738  
      * This does not filter out any rows with a capability the user
 739  
      * does not have in a canselect column, nor did it ever filter
 740  
      * out rows deleted according to a "deleted" column.
 741  
      * But the caller usually gets a second chance to do both.
 742  
      * @return an SQL fragment
 743  
      */
 744  
     String whereClause(Persistent criteria);
 745  
 
 746  
     /**
 747  
      * Return an SQL WHERE clause to select rows using the given object
 748  
      * as a selection criteria and optionally deleted rows or those
 749  
      * included rows the user is not capable of selecting.
 750  
      * <p>
 751  
      * This is currently implemented in terms of
 752  
      * {@link org.melati.poem.Table#appendWhereClause(StringBuffer, org.melati.poem.Persistent)}.
 753  
      * @return an SQL fragment
 754  
      */
 755  
     String whereClause(Persistent criteria,
 756  
                               boolean includeDeleted, boolean excludeUnselectable);
 757  
 
 758  
     /**
 759  
      * @return an SQL fragment
 760  
      * @see #cnfWhereClause(java.util.Enumeration, boolean, boolean)
 761  
      * @see #whereClause(org.melati.poem.Persistent)
 762  
      */
 763  
     String cnfWhereClause(Enumeration<P> persistents);
 764  
 
 765  
     /**
 766  
      * Return a Conjunctive Normal Form (CNF) where clause.
 767  
      * See http://en.wikipedia.org/wiki/Conjunctive_normal_form.
 768  
      *
 769  
      * @return an SQL fragment
 770  
      */
 771  
     String cnfWhereClause(Enumeration<P> persistents,
 772  
                                  boolean includeDeleted, boolean excludeUnselectable);
 773  
 
 774  
     /**
 775  
      * All the objects in the table which refer to a given object.  If none of
 776  
      * the table's columns are reference columns, the <TT>Enumeration</TT>
 777  
      * returned will obviously be empty.
 778  
      * <p>
 779  
      * It is not guaranteed to be quick to execute!
 780  
      *
 781  
      * @return an <TT>Enumeration</TT> of <TT>Persistent</TT>s
 782  
      */
 783  
 
 784  
     Enumeration<P> referencesTo(Persistent object);
 785  
 
 786  
     /**
 787  
      * All the columns in the table which refer to the given table.
 788  
      *
 789  
      * @param table the table to count the references within
 790  
      * @return an Enumeration of Columns referring to the specified Table
 791  
      */
 792  
     Enumeration<Column<?>> referencesTo(Table<?> table);
 793  
 
 794  
     /**
 795  
      * @return the current highest troid
 796  
      */
 797  
     int getMostRecentTroid();
 798  
 
 799  
     /**
 800  
      * @param persistent unused parameter, but might be needed in another troid schema
 801  
      * @return the next Troid
 802  
      */
 803  
     Integer troidFor(Persistent persistent);
 804  
 
 805  
     /**
 806  
      * Write a new row containing the given object.
 807  
      * <p>
 808  
      * The given object will be assigned the next troid and its internal
 809  
      * state will also be modified.
 810  
      *
 811  
      * @exception org.melati.poem.InitialisationPoemException The object failed validation
 812  
      *   (currently one of its field values failed).
 813  
      */
 814  
     void create(Persistent p)
 815  
          throws AccessPoemException, ValidationPoemException,
 816  
             InitialisationPoemException;
 817  
 
 818  
     /**
 819  
      * Create a new object (record) in the table.
 820  
      *
 821  
      * @param initialiser         A piece of code for setting the new object's
 822  
      *                            initial values.  You'll probably want to define
 823  
      *                            it as an anonymous class.
 824  
      *
 825  
      * @return A <TT>Persistent</TT> representing the new object, or, if the
 826  
      *         table was defined in the DSD under the name <TT><I>foo</I></TT>,
 827  
      *         an application-specialised subclass <TT><I>Foo</I></TT> of
 828  
      *         <TT>Persistent</TT>.
 829  
      *
 830  
      * @exception org.melati.poem.AccessPoemException
 831  
      *                if <TT>initialiser</TT> provokes one during its work (which
 832  
      *                is unlikely, since POEM's standard checks are disabled
 833  
      *                while it runs)
 834  
      * @exception org.melati.poem.ValidationPoemException
 835  
      *                if <TT>initialiser</TT> provokes one during its work
 836  
      * @exception org.melati.poem.InitialisationPoemException
 837  
      *                if the object is left by <TT>initialiser</TT> in a state in
 838  
      *                which not all of its fields have legal values, or in which
 839  
      *                the calling thread would not be allowed write access to the
 840  
      *                object under its <TT>AccessToken</TT>---<I>i.e.</I> you
 841  
      *                can't create objects you wouldn't be allowed to write to.
 842  
      *
 843  
      * @see org.melati.poem.Initialiser#init(Persistent)
 844  
      * @see org.melati.poem.PoemThread#accessToken()
 845  
      * @see #getCanCreate()
 846  
      */
 847  
     Persistent create(Initialiser initialiser)
 848  
         throws AccessPoemException, ValidationPoemException,
 849  
                InitialisationPoemException;
 850  
 
 851  
     /**
 852  
      * @return A freshly minted floating <TT>Persistent</TT> object for this table,
 853  
      * ie one without a troid set
 854  
      */
 855  
     Persistent newPersistent();
 856  
 
 857  
     /**
 858  
      * It is the programmer's responsibility to ensure that the where clause
 859  
      * is suitable for the target DBMS.
 860  
      *
 861  
      * @param whereClause the criteria
 862  
      */
 863  
     void delete_unsafe(String whereClause);
 864  
 
 865  
     /**
 866  
      * The number of `extra' (non-DSD-defined) columns in the table.
 867  
      */
 868  
     int extrasCount();
 869  
 
 870  
     /**
 871  
      * The capability required for reading records from the table, unless
 872  
      * overridden in the record itself.  This simply comes from the table's
 873  
      * record in the <TT>tableinfo</TT> table.
 874  
      *
 875  
      * @return the capability needed to read this table
 876  
      */
 877  
     Capability getDefaultCanRead();
 878  
 
 879  
     /**
 880  
      * The capability required for updating records in the table, unless
 881  
      * overridden in the record itself.  This simply comes from the table's
 882  
      * record in the <TT>tableinfo</TT> table.
 883  
      *
 884  
      * @return the default  {@link org.melati.poem.Capability} required to write  a
 885  
      *         {@link org.melati.poem.Persistent}, if any
 886  
      */
 887  
     Capability getDefaultCanWrite();
 888  
 
 889  
     /**
 890  
      * The capability required for deleting records in the table, unless
 891  
      * overridden in the record itself.  This simply comes from the table's
 892  
      * record in the <TT>tableinfo</TT> table.
 893  
      * @return the default  {@link org.melati.poem.Capability} required to delete a
 894  
      *         {@link org.melati.poem.Persistent}, if any
 895  
      */
 896  
     Capability getDefaultCanDelete();
 897  
 
 898  
     /**
 899  
      * The capability required for creating records in the table.  This simply
 900  
      * comes from the table's record in the <TT>tableinfo</TT> table.
 901  
      *
 902  
      * @return the Capability required to write to this table
 903  
      * @see #create(Initialiser)
 904  
      */
 905  
     Capability getCanCreate();
 906  
 
 907  
     /**
 908  
      * @return the canReadColumn or the canSelectColumn or null
 909  
      */
 910  
     Column<Capability> canReadColumn();
 911  
 
 912  
     /**
 913  
      * @return the canSelectColumn or null
 914  
      */
 915  
     Column<Capability> canSelectColumn();
 916  
 
 917  
     /**
 918  
      * @return the canWriteColumn or null
 919  
      */
 920  
     Column<Capability> canWriteColumn();
 921  
 
 922  
     /**
 923  
      * @return the canDeleteColumn or null
 924  
      */
 925  
     Column<Capability> canDeleteColumn();
 926  
 
 927  
     /**
 928  
      * Add a {@link org.melati.poem.Column} to the database and the {@link org.melati.poem.TableInfo} table.
 929  
      *
 930  
      * @param infoP the meta data about the {@link org.melati.poem.Column}
 931  
      * @return the newly added column
 932  
      */
 933  
     Column<?> addColumnAndCommit(ColumnInfo infoP) throws PoemException;
 934  
 
 935  
     /**
 936  
      * @param columnInfo metadata about the column to delete, which is itself deleted
 937  
      */
 938  
     void deleteColumnAndCommit(ColumnInfo columnInfo) throws PoemException;
 939  
 
 940  
     /**
 941  
      * A concise string to stand in for the table.  The table's name and a
 942  
      * description of where it was defined (the DSD, the metadata tables or the
 943  
      * JDBC metadata).
 944  
      * {@inheritDoc}
 945  
      * @see Object#toString()
 946  
      */
 947  
     String toString();
 948  
 
 949  
     /**
 950  
      * Print some diagnostic information about the contents and consistency of
 951  
      * POEM's cache for this table to stderr.
 952  
      */
 953  
     void dumpCacheAnalysis();
 954  
 
 955  
     /**
 956  
      * Print information about the structure of the table to stdout.
 957  
      */
 958  
     void dump();
 959  
 
 960  
     /**
 961  
      * Print information to PrintStream.
 962  
      *
 963  
      * @param ps PrintStream to dump to
 964  
      */
 965  
     void dump(PrintStream ps);
 966  
 
 967  
     /**
 968  
      * A mechanism for caching a selection of records.
 969  
      *
 970  
      * It is the programmer's responsibility to ensure that the where clause
 971  
      * is suitable for the target DBMS.
 972  
      *
 973  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 974  
      * @param orderByClause which field to order by or null
 975  
      * @return the results
 976  
      */
 977  
     CachedSelection<P> cachedSelection(String whereClause,
 978  
                                              String orderByClause);
 979  
 
 980  
     /**
 981  
      * A mechanism for caching a record count.
 982  
      *
 983  
      * It is the programmer's responsibility to ensure that the where clause
 984  
      * is suitable for the target DBMS.
 985  
      *
 986  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 987  
      * @param includeDeleted whether to include soft deleted records
 988  
      * @return a cached count
 989  
      */
 990  
     CachedCount cachedCount(String whereClause, boolean includeDeleted);
 991  
 
 992  
     /**
 993  
      * A mechanism for caching a record count.
 994  
      *
 995  
      * It is the programmer's responsibility to ensure that the where clause
 996  
      * is suitable for the target DBMS.
 997  
      *
 998  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 999  
      * @param includeDeleted whether to include soft deleted records
 1000  
      * @param excludeUnselectable whether to exclude columns which cannot be selected
 1001  
      * @return a cached count
 1002  
      */
 1003  
     CachedCount cachedCount(String whereClause, boolean includeDeleted,
 1004  
                                    boolean excludeUnselectable);
 1005  
 
 1006  
     /**
 1007  
      * A mechanism for caching a record count.
 1008  
      *
 1009  
      * @param criteria a {@link org.melati.poem.Persistent} with selection fields filled
 1010  
      * @param includeDeleted whether to include soft deleted records
 1011  
      * @param excludeUnselectable whether to exclude columns which cannot be selected
 1012  
      * @return a cached count
 1013  
      */
 1014  
     CachedCount cachedCount(Persistent criteria, boolean includeDeleted,
 1015  
                                    boolean excludeUnselectable);
 1016  
 
 1017  
     /**
 1018  
      * @param criteria a Persistent to extract where clause from
 1019  
      * @return a CachedCount of records matching Criteria
 1020  
      */
 1021  
     CachedCount cachedCount(Persistent criteria);
 1022  
 
 1023  
     /**
 1024  
      * A mechanism for caching a record count.
 1025  
      *
 1026  
      * It is the programmer's responsibility to ensure that the where clause
 1027  
      * is suitable for the target DBMS.
 1028  
      *
 1029  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 1030  
      * @return a cached count
 1031  
      */
 1032  
     CachedCount cachedCount(String whereClause);
 1033  
 
 1034  
     /**
 1035  
      * @return a cached count of all records in the table, 
 1036  
      * obeying includedDeleted and other exclusions
 1037  
      */
 1038  
     CachedCount cachedCount();
 1039  
 
 1040  
     /**
 1041  
      * A mechanism for caching an existance.
 1042  
      *
 1043  
      * It is the programmer's responsibility to ensure that the where clause
 1044  
      * is suitable for the target DBMS.
 1045  
      *
 1046  
      * NOTE It is possible for the count to be written simultaneously,
 1047  
      * but the cache will end up with the same result.
 1048  
      *
 1049  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 1050  
      * @return a cached exists
 1051  
      */
 1052  
     CachedExists cachedExists(String whereClause);
 1053  
 
 1054  
     /**
 1055  
      * A mechanism for caching a record count.
 1056  
      *
 1057  
      * It is the programmer's responsibility to ensure that the where clause
 1058  
      * is suitable for the target DBMS.
 1059  
      *
 1060  
      * @param whereClause raw SQL selection clause appropriate for this DBMS
 1061  
      * @param orderByClause raw SQL order clause appropriate for this DBMS
 1062  
      * @param nullable whether the ReferencePoemType is nullable
 1063  
      * @return a {@link org.melati.poem.RestrictedReferencePoemType}
 1064  
      */
 1065  
     RestrictedReferencePoemType<?> cachedSelectionType(String whereClause,
 1066  
                                      String orderByClause, boolean nullable);
 1067  
 
 1068  
     /**
 1069  
      * Make up a <TT>Field</TT> object whose possible values are a selected
 1070  
      * subset of the records in the table.  You can make a "dropdown" offering a
 1071  
      * choice of your green customers by putting this in your handler
 1072  
      *
 1073  
      * <BLOCKQUOTE><PRE>
 1074  
      * context.put("greens",
 1075  
      *             melati.getDatabase().getCustomerTable().cachedSelectionField(
 1076  
      *                 "colour = 'green'", null, true, null, "greens"));
 1077  
      * </PRE></BLOCKQUOTE>
 1078  
      *
 1079  
      * and this in your template
 1080  
      *
 1081  
      * <BLOCKQUOTE><PRE>
 1082  
      *   Select a customer: $ml.input($greens)
 1083  
      * </PRE></BLOCKQUOTE>
 1084  
      *
 1085  
      * The list of member records is implicitly cached---permanently, and however
 1086  
      * big it turns out to be.  So don't go mad with this.  It is recomputed on
 1087  
      * demand if the contents of the table are changed.  The <TT>whereClause</TT>
 1088  
      * and <TT>orderByClause</TT> you pass in are checked to see if you have
 1089  
      * asked for the same list before, so however many times you call this
 1090  
      * method, you should only trigger actual <TT>SELECT</TT>s when the table
 1091  
      * contents have changed.  The list is also transaction-safe, in that it will
 1092  
      * always reflect the state of affairs within your transaction even if you
 1093  
      * haven't done a commit.
 1094  
      *
 1095  
      * It is the programmer's responsibility to ensure that the where clause
 1096  
      * is suitable for the target DBMS.
 1097  
      *
 1098  
      * @param whereClause         an SQL expression (the bit after the
 1099  
      *                            <TT>SELECT</TT> ... <TT>WHERE</TT>) for picking
 1100  
      *                            out the records you want
 1101  
      *
 1102  
      * @param orderByClause       a comma-separated list of column names which
 1103  
      *                            determine the order in which the records are
 1104  
      *                            presented; if this is <TT>null</TT>, the
 1105  
      *                            <TT>displayorderpriority</TT> attributes of the
 1106  
      *                            table's columns determine the order
 1107  
      *
 1108  
      * @param nullable            whether to allow a blank <TT>NULL</TT> option
 1109  
      *                            as the first possibility
 1110  
      *
 1111  
      * @param selectedTroid       the troid of the record to which the
 1112  
      *                            <TT>SELECT</TT> field should initially be set
 1113  
      *
 1114  
      * @param nameP               the HTML name attribute of the field,
 1115  
      *                            <I>i.e.</I>
 1116  
      *                            <TT>&lt;SELECT NAME=<I>name</I>&gt;</TT>
 1117  
      * @return a Field object
 1118  
      */
 1119  
     Field<?> cachedSelectionField(
 1120  
         String whereClause, String orderByClause, boolean nullable,
 1121  
         Integer selectedTroid, String nameP);
 1122  
 
 1123  
     /**
 1124  
      * Don't call this in your application code.
 1125  
      * Columns should be defined either in the DSD (in which
 1126  
      * case the boilerplate code generated by the preprocessor will call this
 1127  
      * method) or directly in the RDBMS (in which case the initialisation code
 1128  
      * will).
 1129  
      */
 1130  
     void defineColumn(Column<?> column)
 1131  
         throws DuplicateColumnNamePoemException,
 1132  
                DuplicateTroidColumnPoemException,
 1133  
                DuplicateDeletedColumnPoemException;
 1134  
 
 1135  
     /**
 1136  
      * @return incremented extra columns index
 1137  
      */
 1138  
     int getNextExtrasIndex();
 1139  
 
 1140  
     /**
 1141  
      * @param tableInfo the TableInfo to set
 1142  
      */
 1143  
     void setTableInfo(TableInfo tableInfo);
 1144  
 
 1145  
     /**
 1146  
      * @return the {@link org.melati.poem.TableInfo} for this table.
 1147  
      */
 1148  
     TableInfo getTableInfo();
 1149  
 
 1150  
     /**
 1151  
      * @return a DBMS table type eg TEXT 
 1152  
      */
 1153  
     String getDbmsTableType();
 1154  
     
 1155  
 
 1156  
     /**
 1157  
      * Match columnInfo with this Table's columns.
 1158  
      * Conversely, create a ColumnInfo for any columns which don't have one.
 1159  
      */
 1160  
     void unifyWithColumnInfo() throws PoemException;
 1161  
 
 1162  
     /** Unify SQL REMARKS with table.description.
 1163  
      * 
 1164  
      * @param tableDescriptions a JDBC {@link java.sql.ResultSet} with cursor at current row
 1165  
      */
 1166  
     void unifyWithMetadata(ResultSet tableDescriptions) throws SQLException;
 1167  
     
 1168  
     /**
 1169  
      * Unify the JDBC description of this tables columns with the
 1170  
      * meta data held in the {@link org.melati.poem.TableInfo}
 1171  
      *
 1172  
      * @param colDescs a JDBC {@link java.sql.ResultSet} describing the columns with cursor at current row
 1173  
      * @param primaryKey name of primary key column
 1174  
      */
 1175  
     void unifyWithDB(ResultSet colDescs, String primaryKey)
 1176  
         throws PoemException;
 1177  
 
 1178  
     String defaultDisplayName();
 1179  
 
 1180  
     String defaultDescription();
 1181  
 
 1182  
     int defaultDisplayOrder();
 1183  
 
 1184  
     Integer defaultCacheLimit();
 1185  
 
 1186  
     boolean defaultRememberAllTroids();
 1187  
 
 1188  
     String defaultCategory();
 1189  
 
 1190  
 
 1191  
 }