| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| Persistent |
|
| 1.0;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 java.io.PrintStream; | |
| 49 | import java.util.Enumeration; | |
| 50 | import java.util.Map; | |
| 51 | ||
| 52 | /** | |
| 53 | * The object representing a single table row; this is the <B>PO</B> in POEM! | |
| 54 | * <p> | |
| 55 | * Instances are also used to represent selection criteria. | |
| 56 | * | |
| 57 | * @author timp | |
| 58 | * @since 4 Jul 2007 | |
| 59 | * | |
| 60 | */ | |
| 61 | public interface Persistent extends Persistable, Treeable { | |
| 62 | ||
| 63 | /** | |
| 64 | * @return whether this object has been persisted | |
| 65 | */ | |
| 66 | boolean statusNonexistent(); | |
| 67 | ||
| 68 | /** | |
| 69 | * @return whether this object has been deleted | |
| 70 | */ | |
| 71 | boolean statusExistent(); | |
| 72 | ||
| 73 | /** | |
| 74 | * A convenience method to create this Persistent. | |
| 75 | */ | |
| 76 | void makePersistent(); | |
| 77 | ||
| 78 | /** | |
| 79 | * The Table from which the object comes, | |
| 80 | * complete with metadata. | |
| 81 | * @return the Table | |
| 82 | */ | |
| 83 | Table<?> getTable(); | |
| 84 | ||
| 85 | /** | |
| 86 | * @param table | |
| 87 | */ | |
| 88 | //void setTable(Table table, Integer Troid); | |
| 89 | ||
| 90 | /** | |
| 91 | * @return The database from which the object comes. <I>I.e.</I> | |
| 92 | * <TT>getTable().getDatabase()</TT>. | |
| 93 | */ | |
| 94 | Database getDatabase(); | |
| 95 | ||
| 96 | /** | |
| 97 | * Lock without actually reading. | |
| 98 | */ | |
| 99 | void existenceLock(); | |
| 100 | ||
| 101 | /** | |
| 102 | * Check that you have read access to the object. Which is to say: the | |
| 103 | * <TT>AccessToken</TT> associated with the POEM task executing in the | |
| 104 | * running thread confers the <TT>Capability</TT> required for inspecting the | |
| 105 | * object's fields. The access token is set when the task is invoked using | |
| 106 | * <TT>Database.inSession</TT>. The capability is determined by | |
| 107 | * <TT>getCanRead</TT>, which by default means the capability defined in the | |
| 108 | * record's <TT>canread</TT> field in the database. If that's <TT>null</TT>, | |
| 109 | * the table's default <TT>canread</TT> capability is obtained using | |
| 110 | * <TT>getTable().getDefaultCanRead()</TT>. If that is <TT>null</TT> as | |
| 111 | * well, access is granted unconditionally. | |
| 112 | * | |
| 113 | * <P> | |
| 114 | * | |
| 115 | * Although this check can in theory be quite time-consuming, in practice | |
| 116 | * this isn't a problem, because the most recent access token for which the | |
| 117 | * check succeeded is cached; repeat accesses from within the same | |
| 118 | * transaction are therefore quick. | |
| 119 | * | |
| 120 | * <P> | |
| 121 | * | |
| 122 | * Application programmers can override this method to implement their own | |
| 123 | * programmatic access policies. For instance, POEM's own <TT>TableInfo</TT> | |
| 124 | * class overrides it with an empty method in order to disable all read | |
| 125 | * protection on <TT>TableInfo</TT> objects. More interestingly, you could | |
| 126 | * implement a check that depends on the values of the object's fields: | |
| 127 | * for example, you could allow read access to an invoice record to its | |
| 128 | * issuing and receiving parties. | |
| 129 | * | |
| 130 | * @param token the access token on the basis of which readability is | |
| 131 | * being claimed | |
| 132 | * | |
| 133 | * @exception AccessPoemException if the check fails | |
| 134 | * | |
| 135 | * @see Database#inSession | |
| 136 | * @see JdbcTable#getDefaultCanRead | |
| 137 | * | |
| 138 | */ | |
| 139 | ||
| 140 | void assertCanRead(AccessToken token) throws AccessPoemException; | |
| 141 | ||
| 142 | /** | |
| 143 | * @throws AccessPoemException if current accessToken does not grant read capability | |
| 144 | */ | |
| 145 | void assertCanRead() throws AccessPoemException; | |
| 146 | ||
| 147 | /** | |
| 148 | * @return Whether the object is readable by current AccessToken | |
| 149 | * | |
| 150 | * @see #assertCanRead() | |
| 151 | */ | |
| 152 | ||
| 153 | boolean getReadable(); | |
| 154 | ||
| 155 | /** | |
| 156 | * Check that you have write access to the object. Which is to say: the | |
| 157 | * <TT>AccessToken</TT> associated with the POEM task executing in the | |
| 158 | * running thread confers the <TT>Capability</TT> required for updating the | |
| 159 | * object's fields. The remarks made about <TT>assertCanRead</TT> apply | |
| 160 | * (<I>mutatis mutandis</I>) here as well. | |
| 161 | * | |
| 162 | * @see #assertCanRead() | |
| 163 | * @see JdbcTable#getDefaultCanWrite | |
| 164 | */ | |
| 165 | ||
| 166 | void assertCanWrite(AccessToken token) throws AccessPoemException; | |
| 167 | ||
| 168 | /** | |
| 169 | * @throws AccessPoemException if current accessToken does not grant wraite capability | |
| 170 | */ | |
| 171 | void assertCanWrite() throws AccessPoemException; | |
| 172 | ||
| 173 | /** | |
| 174 | * Check that you have delete access to the object. Which is to say: the | |
| 175 | * <TT>AccessToken</TT> associated with the POEM task executing in the | |
| 176 | * running thread confers the <TT>Capability</TT> required for updating the | |
| 177 | * object's fields. The remarks made about <TT>assertCanRead</TT> apply | |
| 178 | * (<I>mutatis mutandis</I>) here as well. | |
| 179 | * | |
| 180 | * @see #assertCanRead() | |
| 181 | * @see JdbcTable#getDefaultCanDelete | |
| 182 | * | |
| 183 | */ | |
| 184 | ||
| 185 | void assertCanDelete(AccessToken token) throws AccessPoemException; | |
| 186 | ||
| 187 | /** | |
| 188 | * @throws AccessPoemException if current accessToken does not grant delete capability | |
| 189 | */ | |
| 190 | void assertCanDelete() throws AccessPoemException; | |
| 191 | ||
| 192 | /** | |
| 193 | * Check that you have create access to the object. Which is to say: the | |
| 194 | * <TT>AccessToken</TT> associated with the POEM task executing in the | |
| 195 | * running thread confers the <TT>Capability</TT> required for creating the | |
| 196 | * object. The capability is determined solely by <TT>getCanCreate</TT> | |
| 197 | * from the table. Unlike <TT>assertCanRead</TT> and <TT>assertCanWrite</TT> | |
| 198 | * there is no idea of having a default <TT>Capability</TT> defined | |
| 199 | * in the table which could be overridden by a <TT>canwrite</TT> field | |
| 200 | * in the persistent (since the persistent has not yet been been written). | |
| 201 | * | |
| 202 | * <P> | |
| 203 | * | |
| 204 | * Application programmers can override this method to implement their own | |
| 205 | * programmatic access policies. | |
| 206 | * | |
| 207 | * @see #assertCanRead() | |
| 208 | * @see #assertCanWrite() | |
| 209 | * @see JdbcTable#getCanCreate | |
| 210 | */ | |
| 211 | ||
| 212 | void assertCanCreate(AccessToken token); | |
| 213 | ||
| 214 | /** | |
| 215 | * @throws AccessPoemException if current accessToken does not grant create capability | |
| 216 | */ | |
| 217 | void assertCanCreate() throws AccessPoemException; | |
| 218 | ||
| 219 | /** | |
| 220 | * The `identifying value' of one of the object's fields. This is the value | |
| 221 | * which is actually stored in the database, given to you as a basic Java | |
| 222 | * type; currently, the only fields for which this differs from the `true | |
| 223 | * value' returned from <TT>getCooked</TT> are reference fields with type | |
| 224 | * <TT>ReferencePoemType</TT> and <TT>StringKeyReferencePoemType</TT>. | |
| 225 | * | |
| 226 | * <P> | |
| 227 | * | |
| 228 | * If the field <TT><I>baz</I></TT> is defined in the DSD as part of a table | |
| 229 | * called <TT><I>foo</I></TT>, then the table's records will be represented | |
| 230 | * by an application-specialised subclass of <TT>Persistent</TT> called | |
| 231 | * <TT><I>Foo</I></TT> which provides a typed <TT>get<I>Baz</I></TT> method. | |
| 232 | * So the easiest way to be sure of your types is to predeclare any fields | |
| 233 | * you use in the DSD, use the typed field-access methods, and let the | |
| 234 | * compiler take the strain. When working with generic <TT>Persistent</TT>s, | |
| 235 | * you probably want to use <TT>getField</TT>. | |
| 236 | * | |
| 237 | * <P> | |
| 238 | * | |
| 239 | * The value returned is relative to the transaction associated with the | |
| 240 | * calling thread, as set up by <TT>Database.inSession</TT>. This means that | |
| 241 | * you never see the value of a field change in your transaction because of | |
| 242 | * another transaction's activities, unless you do a | |
| 243 | * <TT>PoemThread.commit()</TT> or a <TT>PoemThread.rollback()</TT>. If you | |
| 244 | * need to, you can store a <TT>Persistent</TT> in a permanent data structure | |
| 245 | * and access it in different sessions over time---or even from concurrently | |
| 246 | * running sessions, though this may slow down access checking; each | |
| 247 | * transaction will see the value it expects. | |
| 248 | * | |
| 249 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 250 | * column in the RDBMS and DSD) | |
| 251 | * | |
| 252 | * @return The field's `identifying value'; this will be a <TT>String</TT>, | |
| 253 | * <TT>Boolean</TT>, <TT>Integer</TT>, <TT>Double</TT> or | |
| 254 | * <TT>Date</TT> as appropriate. If the field is a reference field, | |
| 255 | * the result is an <TT>Integer</TT> giving the troid of the referee. | |
| 256 | * If you want references to be resolved transparently to | |
| 257 | * <TT>Persistent</TT>s, use <TT>getCooked</TT>. | |
| 258 | * If you want a string representation of the field, | |
| 259 | * use <TT>getRawString</TT> or <TT>getCookedString</TT>. | |
| 260 | * | |
| 261 | * @exception NoSuchColumnPoemException | |
| 262 | * if the field named doesn't exist | |
| 263 | * @exception AccessPoemException | |
| 264 | * if the calling thread doesn't have read access to the | |
| 265 | * object (see <TT>assertCanRead</TT>) | |
| 266 | * | |
| 267 | * @see #getCooked | |
| 268 | * @see #getRawString | |
| 269 | * @see #getCookedString | |
| 270 | * @see #getField | |
| 271 | * @see Database#inSession | |
| 272 | * @see PoemThread#commit | |
| 273 | * @see PoemThread#rollback | |
| 274 | * @see #assertCanRead() | |
| 275 | */ | |
| 276 | Object getRaw(String name) throws NoSuchColumnPoemException, | |
| 277 | AccessPoemException; | |
| 278 | ||
| 279 | /** | |
| 280 | * A string representation of the `identifying value' of one of the object's | |
| 281 | * fields. The value returned is relative to the transaction associated with | |
| 282 | * the calling thread, as set up by <TT>Database.inSession</TT>: see the | |
| 283 | * remarks made about <TT>getRaw</TT>. | |
| 284 | * | |
| 285 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 286 | * column in the RDBMS and DSD) | |
| 287 | * | |
| 288 | * @return Roughly, the string the underlying RDBMS would display if asked | |
| 289 | * to show the field's value. If you want reference fields to be | |
| 290 | * represented by their referee's <TT>displayString()</TT> (by | |
| 291 | * default, its primary display field) rather than by its troid, use | |
| 292 | * <TT>getCookedString</TT>. If you want the field's value as an | |
| 293 | * appropriate Java type like <TT>Integer</TT>, use <TT>getRaw</TT> | |
| 294 | * or <TT>getCooked</TT>---or an equivalent, but type-safe, method | |
| 295 | * derived from the DSD. | |
| 296 | * | |
| 297 | * @exception NoSuchColumnPoemException | |
| 298 | * if the field named doesn't exist | |
| 299 | * @exception AccessPoemException | |
| 300 | * if the calling thread doesn't have read access to the | |
| 301 | * object (see <TT>assertCanRead</TT>) | |
| 302 | * | |
| 303 | * @see #getCookedString | |
| 304 | * @see #getRaw | |
| 305 | * @see #getCooked | |
| 306 | * @see #assertCanRead() | |
| 307 | */ | |
| 308 | ||
| 309 | String getRawString(String name) throws AccessPoemException, | |
| 310 | NoSuchColumnPoemException; | |
| 311 | ||
| 312 | /** | |
| 313 | * Set the `identifying value' of one of the record's fields. This is the | |
| 314 | * value which is actually stored in the database, given by you as a basic | |
| 315 | * Java type; currently, the only fields for which this differs from the | |
| 316 | * `true value' expected by <TT>setCooked</TT> are reference fields with type | |
| 317 | * <TT>ReferencePoemType</TT>. | |
| 318 | * | |
| 319 | * <P> | |
| 320 | * | |
| 321 | * If the field <TT><I>baz</I></TT> is defined in the DSD as part of a table | |
| 322 | * called <TT><I>foo</I></TT>, then the table's records will be represented | |
| 323 | * by an application-specialised subclass of <TT>Persistent</TT> called | |
| 324 | * <TT><I>Foo</I></TT> which provides a typed <TT>set<I>Baz</I></TT> | |
| 325 | * method. So the easiest way to be sure of your types is to predeclare any | |
| 326 | * fields you use in the DSD, use the typed field-access methods, and let the | |
| 327 | * compiler take the strain. When working with generic <TT>Persistent</TT>s, | |
| 328 | * you probably mean <TT>setRawString</TT> anyway. | |
| 329 | * | |
| 330 | * <P> | |
| 331 | * | |
| 332 | * The change you make to the field's value will only be visible to the | |
| 333 | * calling thread, until it successfully completes the task started by | |
| 334 | * <TT>Database.inSession</TT>, or does an explicit | |
| 335 | * <TT>PoemThread.commit()</TT>. Up to that point the change can be undone | |
| 336 | * by calling <TT>PoemThread.rollback()</TT>, and will be undone | |
| 337 | * automatically if the task terminates with an uncaught exception. | |
| 338 | * | |
| 339 | * <P> | |
| 340 | * | |
| 341 | * In fact, your changes are not written down to the database, even relative | |
| 342 | * to an uncommitted transaction, until it's actually necessary. So multiple | |
| 343 | * calls to <TT>setRaw</TT> and relatives will not cause multiple SQL | |
| 344 | * <TT>UPDATE</TT>s to be issued. | |
| 345 | * | |
| 346 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 347 | * column in the RDBMS and DSD) | |
| 348 | * | |
| 349 | * @param raw The new value for the field: a <TT>String</TT>, | |
| 350 | * <TT>Boolean</TT>, <TT>Integer</TT>, <TT>Double</TT> or | |
| 351 | * <TT>Date</TT> as appropriate. If the field is a | |
| 352 | * reference field: an <TT>Integer</TT> giving the troid | |
| 353 | * of the referee. If you want to pass referees as actual | |
| 354 | * <TT>Persistent</TT>s, use <TT>setCooked</TT>. If you | |
| 355 | * want to set the field from a string representation | |
| 356 | * (<I>e.g.</I> typed in by the user), use | |
| 357 | * <TT>setRawString</TT>. | |
| 358 | * | |
| 359 | * @exception NoSuchColumnPoemException | |
| 360 | * if the field named doesn't exist | |
| 361 | * @exception AccessPoemException | |
| 362 | * if the calling thread doesn't have write access to the | |
| 363 | * object (see <TT>assertCanWrite</TT>) | |
| 364 | * @exception ValidationPoemException | |
| 365 | * if <TT>raw</TT> is not a valid value for the field | |
| 366 | * (<I>e.g.</I> a string is too long) | |
| 367 | * | |
| 368 | * @see #setCooked | |
| 369 | * @see #setRawString | |
| 370 | * @see #assertCanWrite() | |
| 371 | * @see Database#inSession | |
| 372 | * @see PoemThread#commit | |
| 373 | * @see PoemThread#rollback | |
| 374 | */ | |
| 375 | ||
| 376 | void setRaw(String name, Object raw) throws NoSuchColumnPoemException, | |
| 377 | AccessPoemException, ValidationPoemException; | |
| 378 | ||
| 379 | /** | |
| 380 | * Set the `identifying value' of one of the record's fields from a string | |
| 381 | * representation. The remarks about sessions (transactions) and DSD-derived | |
| 382 | * type-safe methods made for <TT>setRaw</TT> apply here too. | |
| 383 | * | |
| 384 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 385 | * column in the RDBMS and DSD) | |
| 386 | * | |
| 387 | * @param string A string that will be parsed to obtain the new value | |
| 388 | * for the field. If it's a reference field, this should | |
| 389 | * be a decimal representation of the referee's troid. If | |
| 390 | * you want to set fields to values defined by appropriate | |
| 391 | * Java types, use <TT>setRaw</TT> or <TT>setCooked</TT>. | |
| 392 | * | |
| 393 | * @exception NoSuchColumnPoemException | |
| 394 | * if the field named doesn't exist | |
| 395 | * @exception AccessPoemException | |
| 396 | * if the calling thread doesn't have write access to the | |
| 397 | * object (see <TT>assertCanWrite</TT>) | |
| 398 | * @exception ParsingPoemException | |
| 399 | * if <TT>string</TT> doesn't parse as a value of the | |
| 400 | * appropriate type | |
| 401 | * @exception ValidationPoemException | |
| 402 | * if <TT>string</TT> parses to an invalid value for the field | |
| 403 | * (<I>e.g.</I> it's too wide) | |
| 404 | * | |
| 405 | * @see #setRaw | |
| 406 | * @see #setCooked | |
| 407 | * @see #assertCanWrite() | |
| 408 | */ | |
| 409 | ||
| 410 | void setRawString(String name, String string) | |
| 411 | throws NoSuchColumnPoemException, AccessPoemException, | |
| 412 | ParsingPoemException, ValidationPoemException; | |
| 413 | ||
| 414 | /** | |
| 415 | * The `true value' of one of the object's fields. This is the | |
| 416 | * fully-interpreted value rather than the one actually stored in the | |
| 417 | * database; currently, the only fields for which this differs from the | |
| 418 | * `identifying value' return from <TT>getRaw</TT> are reference fields | |
| 419 | * with type <TT>ReferencePoemType</TT>. | |
| 420 | * | |
| 421 | * <P> | |
| 422 | * | |
| 423 | * The value returned is relative to the transaction associated with the | |
| 424 | * calling thread, as set up by <TT>Database.inSession</TT>: see the remarks | |
| 425 | * made about <TT>getRaw</TT>. | |
| 426 | * | |
| 427 | * <P> | |
| 428 | * | |
| 429 | * The easiest way to be sure of your types is to predeclare any fields you | |
| 430 | * use in the DSD, or use <TT>getField</TT>. Again, see the remarks made | |
| 431 | * about <TT>getRaw</TT>. | |
| 432 | * | |
| 433 | * @return The field's `true value'; this will be a <TT>String</TT>, | |
| 434 | * <TT>Boolean</TT>, <TT>Integer</TT>, <TT>Double</TT>, | |
| 435 | * <TT>Date</TT>, or, if the field is a reference field, a | |
| 436 | * <TT>Persistent</TT> representing the referee. If you just want to | |
| 437 | * see referees' troids, use <TT>getRaw</TT>. If you want a string | |
| 438 | * representation of the field, use <TT>getRawString</TT> or | |
| 439 | * <TT>getCookedString</TT>. | |
| 440 | * | |
| 441 | * @exception NoSuchColumnPoemException | |
| 442 | * if the field named doesn't exist | |
| 443 | * @exception AccessPoemException | |
| 444 | * if the calling thread doesn't have read access to the | |
| 445 | * object (see <TT>assertCanRead</TT>) | |
| 446 | * | |
| 447 | * @see #getRaw | |
| 448 | * @see #getRawString | |
| 449 | * @see #getCookedString | |
| 450 | * @see #getField | |
| 451 | * @see #assertCanRead() | |
| 452 | */ | |
| 453 | ||
| 454 | Object getCooked(String name) throws NoSuchColumnPoemException, | |
| 455 | AccessPoemException; | |
| 456 | ||
| 457 | /** | |
| 458 | * A string representation of the `true value' of one of the object's fields. | |
| 459 | * For example the return value for the user table's category field would be | |
| 460 | * User. | |
| 461 | * The value returned is relative to the transaction associated with the | |
| 462 | * calling thread, as set up by <TT>Database.inSession</TT>: see the remarks | |
| 463 | * made about <TT>getRaw</TT>. | |
| 464 | * | |
| 465 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 466 | * column in the RDBMS and DSD) | |
| 467 | * @param locale A PoemLocale eg PoemLocale.HERE | |
| 468 | * @param style A date format | |
| 469 | * | |
| 470 | * @return The string the underlying RDBMS would display if asked | |
| 471 | * to show the field's value, except that reference fields are | |
| 472 | * represented by their referee's <TT>displayString()</TT> (by | |
| 473 | * default, its primary display field) rather than by its troid. If | |
| 474 | * you want to see troids instead, use <TT>getRawString</TT>. If | |
| 475 | * you want the field's value as an appropriate Java type like | |
| 476 | * <TT>Integer</TT>, use <TT>getRaw</TT> or <TT>getCooked</TT>---or | |
| 477 | * an equivalent, but type-safe, method derived from the DSD. | |
| 478 | * | |
| 479 | * @exception NoSuchColumnPoemException | |
| 480 | * if the field named doesn't exist | |
| 481 | * @exception AccessPoemException | |
| 482 | * if the calling thread doesn't have read access to the | |
| 483 | * object (see <TT>assertCanRead</TT>) | |
| 484 | * | |
| 485 | * @see #getRawString | |
| 486 | * @see #getRaw | |
| 487 | * @see #getCooked | |
| 488 | * @see #assertCanRead() | |
| 489 | * @see #displayString | |
| 490 | */ | |
| 491 | ||
| 492 | String getCookedString(String name, PoemLocale locale, int style) | |
| 493 | throws NoSuchColumnPoemException, AccessPoemException; | |
| 494 | ||
| 495 | /** | |
| 496 | * Set the `true value' of one of the record's fields. Like | |
| 497 | * <TT>setRaw</TT>, but reference fields expect to see a | |
| 498 | * <TT>Persistent</TT> representing their new referee rather than an | |
| 499 | * <TT>Integer</TT> specifying its troid. The remarks about sessions | |
| 500 | * (transactions) and DSD-derived type-safe methods made for | |
| 501 | * <TT>setRaw</TT> apply here too. | |
| 502 | * | |
| 503 | * @param name the name of the field (<I>i.e.</I> the name of the | |
| 504 | * column in the RDBMS and DSD) | |
| 505 | * | |
| 506 | * @param cooked the new value for the field: a <TT>String</TT>, | |
| 507 | * <TT>Boolean</TT>, <TT>Integer</TT>, <TT>Double</TT>, | |
| 508 | * <TT>Date</TT> or, for a reference field, a | |
| 509 | * <TT>Persistent</TT>. If you want to pass referees as | |
| 510 | * troids, use <TT>setRaw</TT>. If you want to set the | |
| 511 | * field from a string representation (<I>e.g.</I> typed | |
| 512 | * in by the user), use <TT>setRawString</TT>. | |
| 513 | * | |
| 514 | * @exception NoSuchColumnPoemException | |
| 515 | * if the field named doesn't exist | |
| 516 | * @exception AccessPoemException | |
| 517 | * if the calling thread doesn't have write access to the | |
| 518 | * object (see <TT>assertCanWrite</TT>) | |
| 519 | * @exception ValidationPoemException | |
| 520 | * if <TT>cooked</TT> is not a valid value for the field | |
| 521 | * (<I>e.g.</I> a string is too long) | |
| 522 | * | |
| 523 | * @see #setRaw | |
| 524 | * @see #setRawString | |
| 525 | * @see #assertCanWrite() | |
| 526 | */ | |
| 527 | ||
| 528 | void setCooked(String name, Object cooked) | |
| 529 | throws NoSuchColumnPoemException, ValidationPoemException, | |
| 530 | AccessPoemException; | |
| 531 | ||
| 532 | /** | |
| 533 | * The value of one of the object's fields, wrapped up with type information | |
| 534 | * sufficient for rendering it. Basically, value plus name plus type. This | |
| 535 | * is the form in which Melati's templating facilities expect to receive | |
| 536 | * values for displaying them or creating input boxes. | |
| 537 | * | |
| 538 | * <P> | |
| 539 | * | |
| 540 | * If the field <TT><I>baz</I></TT> is defined in the DSD as part of a table | |
| 541 | * called <TT><I>foo</I></TT>, then the table's records will be represented | |
| 542 | * by an application-specialised subclass of <TT>Persistent</TT> called | |
| 543 | * <TT><I>Foo</I></TT> which provides a <TT>get<I>Baz</I>Field</TT> method. | |
| 544 | * | |
| 545 | * @param name column name | |
| 546 | * @return the Field of that name | |
| 547 | * @throws NoSuchColumnPoemException if there is no column of that name | |
| 548 | * @throws AccessPoemException if the current AccessToken does not grant access capability | |
| 549 | */ | |
| 550 | Field<?> getField(String name) throws NoSuchColumnPoemException, | |
| 551 | AccessPoemException; | |
| 552 | ||
| 553 | /** | |
| 554 | * Create Fields from Columns. | |
| 555 | * | |
| 556 | * @param columns an Enumeration of Columns | |
| 557 | * @return an Enumeration of Fields | |
| 558 | */ | |
| 559 | Enumeration<Field<?>> fieldsOfColumns(Enumeration<Column<?>> columns); | |
| 560 | ||
| 561 | /** | |
| 562 | * The values of all the object's fields, wrapped up with type information | |
| 563 | * sufficient for rendering them. | |
| 564 | * | |
| 565 | * @return an <TT>Enumeration</TT> of <TT>Field</TT>s | |
| 566 | */ | |
| 567 | ||
| 568 | Enumeration<Field<?>> getFields(); | |
| 569 | ||
| 570 | /** | |
| 571 | * The values of all the object's fields designated for inclusion in full | |
| 572 | * record displays, wrapped up with type information sufficient for rendering | |
| 573 | * them. | |
| 574 | * | |
| 575 | * @return an <TT>Enumeration</TT> of <TT>Field</TT>s | |
| 576 | * @see DisplayLevel#record | |
| 577 | */ | |
| 578 | ||
| 579 | Enumeration<Field<?>> getRecordDisplayFields(); | |
| 580 | ||
| 581 | /** | |
| 582 | * All fields at the detailed display level in display order. | |
| 583 | * | |
| 584 | * @return an <TT>Enumeration</TT> of <TT>Field</TT>s | |
| 585 | * @see DisplayLevel#detail | |
| 586 | */ | |
| 587 | Enumeration<Field<?>> getDetailDisplayFields(); | |
| 588 | ||
| 589 | /** | |
| 590 | * All fields at the summary display level in display order. | |
| 591 | * | |
| 592 | * @return an <TT>Enumeration</TT> of <TT>Field</TT>s | |
| 593 | * @see DisplayLevel#summary | |
| 594 | */ | |
| 595 | Enumeration<Field<?>> getSummaryDisplayFields(); | |
| 596 | ||
| 597 | /** | |
| 598 | * @return an <TT>Enumeration</TT> of searchable <TT>Field</TT>s | |
| 599 | */ | |
| 600 | Enumeration<Field<?>> getSearchCriterionFields(); | |
| 601 | ||
| 602 | /** | |
| 603 | * @return the Primary Display Column as a Field | |
| 604 | */ | |
| 605 | Field<?> getPrimaryDisplayField(); | |
| 606 | ||
| 607 | /** | |
| 608 | * Delete the object. Before the record is deleted from the database, POEM | |
| 609 | * checks to see if it is the target of any reference fields. What happens | |
| 610 | * in this case is determined by the <TT>integrityfix</TT> setting of the | |
| 611 | * referring column, unless that's overridden via the | |
| 612 | * <TT>integrityFixOfColumn</TT> argument. By default, a | |
| 613 | * <TT>DeletionIntegrityPoemException</TT> is thrown, but this behaviour can | |
| 614 | * be changed through the admin interface. | |
| 615 | * | |
| 616 | * @see IntegrityFix | |
| 617 | * @see PoemThread#commit | |
| 618 | * | |
| 619 | * @param integrityFixOfColumn | |
| 620 | * A map from {@link Column} to {@link IntegrityFix} which says | |
| 621 | * how referential integrity is to be maintained for each column | |
| 622 | * that can refer to the object being deleted. May be | |
| 623 | * <TT>null</TT> to mean `empty'. If a column isn't mentioned, | |
| 624 | * the default behaviour for the column is used. (The default | |
| 625 | * is {@link StandardIntegrityFix#prevent}.) | |
| 626 | */ | |
| 627 | void delete(Map<Column<?>, IntegrityFix> integrityFixOfColumn); | |
| 628 | ||
| 629 | /** | |
| 630 | * Delete without access checks. | |
| 631 | */ | |
| 632 | void delete_unsafe(); | |
| 633 | ||
| 634 | /** | |
| 635 | * Delete this persistent, with default integrity checks, | |
| 636 | * ie disallow deletion if object referred to by others. | |
| 637 | */ | |
| 638 | void delete(); | |
| 639 | ||
| 640 | /** | |
| 641 | * Delete the object, with even more safety checks for referential integrity. | |
| 642 | * As {@link #delete(java.util.Map)}, but waits for exclusive access to the | |
| 643 | * database before doing the delete, and commits the session immediately | |
| 644 | * afterwards. | |
| 645 | * <p> | |
| 646 | * This used to be the only deletion entry point allowed, but | |
| 647 | * now we ensure that the possible race condition involving new | |
| 648 | * pointers to the deleted object created during the deletion process is | |
| 649 | * covered. So it is recommended to use {@link #delete(java.util.Map)} | |
| 650 | * unless you really want this functionality. | |
| 651 | * | |
| 652 | */ | |
| 653 | void deleteAndCommit(Map<Column<?>, IntegrityFix> integrityFixOfColumn) | |
| 654 | throws AccessPoemException, DeletionIntegrityPoemException; | |
| 655 | ||
| 656 | /** | |
| 657 | * Convenience method with default integrity fix. | |
| 658 | * | |
| 659 | * @throws AccessPoemException | |
| 660 | * @throws DeletionIntegrityPoemException | |
| 661 | */ | |
| 662 | void deleteAndCommit() throws AccessPoemException, | |
| 663 | DeletionIntegrityPoemException; | |
| 664 | ||
| 665 | /** | |
| 666 | * Create a new object like this one. | |
| 667 | * This Persistent must not be floating. | |
| 668 | * | |
| 669 | * @return A floating clone | |
| 670 | */ | |
| 671 | Persistent duplicated() throws AccessPoemException; | |
| 672 | ||
| 673 | /** | |
| 674 | * Create a new persistent like this one, regardless of | |
| 675 | * whether this Persistent has been written to the dbms yet. | |
| 676 | * | |
| 677 | * @return A floating clone | |
| 678 | */ | |
| 679 | Persistent duplicatedFloating() throws AccessPoemException; | |
| 680 | ||
| 681 | /** | |
| 682 | * A string describing the object for the purposes of rendering it in lists | |
| 683 | * presented to the user. Unless overridden, this returns the value picked | |
| 684 | * out by the designated `primary display column' of the table from which the | |
| 685 | * object comes. If there is no such column, the object's troid is returned | |
| 686 | * (as a decimal string). | |
| 687 | * | |
| 688 | * @param locale our locale | |
| 689 | * @param style | |
| 690 | * a DateFormat (only applicable to those rare objects whose summary column is a date) | |
| 691 | * @return the String to display | |
| 692 | * @throws AccessPoemException | |
| 693 | * if current User does not have viewing {@link Capability} | |
| 694 | */ | |
| 695 | String displayString(PoemLocale locale, int style) | |
| 696 | throws AccessPoemException; | |
| 697 | ||
| 698 | /** | |
| 699 | * Defaults to DateFormat.MEDIUM. | |
| 700 | * @return Default String for display. | |
| 701 | * | |
| 702 | * @throws AccessPoemException | |
| 703 | * if current User does not have viewing {@link Capability} | |
| 704 | */ | |
| 705 | String displayString(PoemLocale locale) throws AccessPoemException; | |
| 706 | ||
| 707 | /** | |
| 708 | * @return Default String for display. | |
| 709 | * | |
| 710 | * @throws AccessPoemException | |
| 711 | * if current User does not have viewing {@link Capability} | |
| 712 | */ | |
| 713 | String displayString() throws AccessPoemException; | |
| 714 | ||
| 715 | /** | |
| 716 | * @return the dump String | |
| 717 | */ | |
| 718 | String dump(); | |
| 719 | ||
| 720 | /** | |
| 721 | * Dump to a PrintStream. | |
| 722 | * @param p the PrintStream to dump to | |
| 723 | */ | |
| 724 | void dump(PrintStream p); | |
| 725 | ||
| 726 | /** | |
| 727 | * Called after this persistent is written to the database | |
| 728 | * on being inserted or modified. | |
| 729 | * <p> | |
| 730 | * This is called after postInsert() or postModify(). | |
| 731 | * <p> | |
| 732 | * This is low level and there is a limit to what you can | |
| 733 | * do here without causing infinitely recursive calls. | |
| 734 | */ | |
| 735 | void postWrite(); | |
| 736 | ||
| 737 | /** | |
| 738 | * Called after this persistent is written to the database | |
| 739 | * for the first time. | |
| 740 | * <p> | |
| 741 | * This is low level and there is a limit to what you can | |
| 742 | * do here without causing infinitely recursive calls. | |
| 743 | */ | |
| 744 | void postInsert(); | |
| 745 | ||
| 746 | /** | |
| 747 | * Called after this persistent is updated and written to the | |
| 748 | * database replacing the existing record it represents. | |
| 749 | * <p> | |
| 750 | * Not called when it is written to the database for the | |
| 751 | * first time. | |
| 752 | * <p> | |
| 753 | * This is low level and there is a limit to what you can | |
| 754 | * do here without causing infinitely recursive calls. | |
| 755 | */ | |
| 756 | void postModify(); | |
| 757 | ||
| 758 | /** | |
| 759 | * Optionally called before an instance is edited by the user. | |
| 760 | * <p> | |
| 761 | * See {@link #postEdit(boolean)} for additional comments. | |
| 762 | * However, it is not called when a newly created row is | |
| 763 | * edited. | |
| 764 | */ | |
| 765 | void preEdit(); | |
| 766 | ||
| 767 | /** | |
| 768 | * Optionally called after this instance is edited by a user. | |
| 769 | * <p> | |
| 770 | * Unlike {@link #postModify()} and {@link #postInsert()} this | |
| 771 | * is not called during write down but can be called by | |
| 772 | * applications after individual field edits by the user | |
| 773 | * have been reflected in the instance. | |
| 774 | * <p> | |
| 775 | * It can be be overridden to enforce data model constraints | |
| 776 | * such as validity of columns relative to other columns. | |
| 777 | * These will be enforced when the admin system is used. | |
| 778 | * <p> | |
| 779 | * This is a higher level method than {@link #postModify()} | |
| 780 | * so is less likely to lead to infinite recursion or other | |
| 781 | * such problems. | |
| 782 | * <p> | |
| 783 | * Sorry for the lack of signature consistency with the | |
| 784 | * lower level methods but I got tired of having to call | |
| 785 | * my own application specific common method. | |
| 786 | * | |
| 787 | * @param creating Are we in the process of creating a new record? | |
| 788 | */ | |
| 789 | void postEdit(boolean creating); | |
| 790 | ||
| 791 | /** | |
| 792 | * @return the dirty | |
| 793 | */ | |
| 794 | boolean isDirty(); | |
| 795 | ||
| 796 | /** | |
| 797 | * @param dirty the dirty to set | |
| 798 | */ | |
| 799 | void setDirty(boolean dirty); | |
| 800 | ||
| 801 | ||
| 802 | } | |
| 803 |