001 /* 002 * Copyright 2001,2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.apache.commons.scaffold.sql; 018 019 020 import java.sql.SQLException; 021 import java.sql.Timestamp; 022 import java.util.Collection; 023 import java.util.Iterator; 024 import java.util.List; 025 import java.util.Map; 026 import java.util.Properties; 027 028 import org.apache.commons.beanutils.BeanUtils; 029 import org.apache.commons.scaffold.lang.ParameterException; 030 import org.apache.commons.scaffold.lang.PopulateException; 031 import org.apache.commons.scaffold.lang.PropertiesException; 032 import org.apache.commons.scaffold.lang.ResourceException; 033 import org.apache.commons.scaffold.lang.Tokens; 034 import org.apache.commons.scaffold.lucene.Engine; 035 import org.apache.commons.scaffold.lucene.SearchUtils; 036 import org.apache.commons.scaffold.text.ConvertUtils; 037 import org.apache.commons.scaffold.util.ProcessBeanBase; 038 import org.apache.commons.scaffold.util.ProcessResult; 039 import org.apache.commons.scaffold.util.ProcessResultBase; 040 import org.apache.commons.scaffold.util.StorageBean; 041 042 // ------------------------------------------------------------------------ 78 043 044 /** 045 * Implements StorageBean interface using 046 * <code>StatementUtils</code> and <code>ResultSetUtils</code> in 047 * this package. Specialty operations may be added using the same 048 * utilities. 049 * <P> 050 * <B>To use this class, the developer must:</B> 051 * <UL> 052 * <LI>Declare a subclass adding the properties to be stored. 053 * <LI>Provide in a set of standard SQL queries naming the properties 054 * to be stored as columns in the command 055 * <LI>Override <code>getStorageKey</code> to return the property used 056 * as the primary or unique key in the SQL commands. 057 * <LI>Override <code>getParameters</code> to return an array of 058 * properties as needed by object's insert and update SQL commands. 059 * <LI>Override <code>getPrefix</code> to set a unique prefix 060 * for each StorageBean class. 061 * Include the prefix in the resource file, but not in the Java code. 062 * <LI>Provide keys.next and keys.inc SQL commands to obtain a new 063 * primary key or override createKey to use some other method. 064 * </UL> 065 * <P> 066 * <B>To specify a connection pool and load the SQL commands:</B> 067 * <UL> 068 * <LI>Load the <code>ConnectionAdaptor</code> for your database 069 * connection pool 070 * <LI>Load the <code>Properties</code> file with your commands and 071 * pass it to the StorageBeanBase <code>init</code> method. 072 * </UL> 073 * <P>The <code>ConnectionServlet</code> in this package is designed 074 * to load <code>ConnectionAdapters<code> and resource 075 * (<code>Properties</code>) files. 076 * <P> 077 * Regarding the queries: 078 * <UL> 079 * <LI>The SQL commands are given in a standard Properties file 080 * (e.g, user.retrieve=SELECT name,address FROM userTable). 081 * The default runtime location is 082 * [WEB-INF/classes/resources/command.properties]. 083 * <LI>See the command.properties.sample file in this package 084 * for a starter file. 085 * <LI>All the subclass share the same Properties file. 086 * The prefix property lets you use the same standard query names for 087 * more than one StorageBean. 088 * <LI>The standard queries are insert, update, retrieve, delete, and 089 * recycle, and restore. 090 * <LI>The insert and update commands should use same columns in same 091 * order. 092 * <LI>The retrieve, delete, recycle, and restore command should use 093 * the storageKey property for selection. 094 * <LI>Hint: If columns cannot follow property naming conventions, 095 * rename column in command 096 * <LI>Hint: You can use the same object for more than one table or 097 * resultset if you like 098 * </UL> 099 * 100 * @todo Refactor recycle,restore,delete to use common util method 101 * @todo Javadocs for new classes 102 * @todo Use reflection to read parameter key and make array from 103 * that. 104 * @todo Check for key.paramlist then paramlist. 105 * @todo Permit each subclass to have its own properties (collection 106 * of properties, like Struts Actions). 107 * @todo Switch to CommandStore (or eliminate that object if not 108 * needed). 109 * @todo Add properties to manage optimistic locking 110 * @todo Change from BeanUtil.populate to copyProperties in 1.1 111 * version. 112 * @author Ted Husted 113 * @author OK State DEQ 114 * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $ 115 */ 116 public class StorageBeanBase extends ProcessBeanBase implements StorageBean { 117 118 119 /** 120 * Convenience method to check for null, empty String. 121 */ 122 protected boolean blank(String s) { 123 return ConvertUtils.blank(s); 124 } 125 126 /** 127 * Convenience method to check for null, empty String, 128 * or "0" String. 129 */ 130 protected boolean blankValue(String s) { 131 return ConvertUtils.blankValue(s); 132 } 133 134 /** 135 * Returns true if null or zero. 136 */ 137 public static boolean blank(Number key) { 138 return ConvertUtils.blank(key); 139 } 140 141 142 143 // ------------------------------------------------------------------ Commands 144 // TODO: Refactor this to use a CommandStore 145 146 147 /** 148 * [:TODO: Javadoc] 149 */ 150 public final static String like(String parameter) { 151 return StatementUtils.like(parameter); 152 } 153 154 155 /** 156 * [:TODO: Javadoc] 157 */ 158 public final static String DOT = "."; 159 160 161 /** 162 * Our command string properties. 163 * Can be loaded from an external properties file at startup. 164 */ 165 protected static Properties commands; 166 167 168 /** 169 * Retrieve command from <code>commands</code> Properties 170 */ 171 protected String lookup(String key) 172 throws PropertiesException { 173 174 if (null==commands) throw new PropertiesException( 175 PropertiesException.MESSAGE + key); 176 177 String command = null; 178 String prefix = getPrefix(); 179 if (null!=prefix) { 180 StringBuffer sb = new StringBuffer(prefix); 181 sb.append(DOT); 182 sb.append(key); 183 command = sb.toString(); 184 } 185 else command = key; 186 187 return commands.getProperty(command); 188 } 189 190 191 /** 192 * Retrieve command from <code>commands</code> Properties 193 */ 194 protected String lookupRoot(String key) 195 throws PropertiesException { 196 197 if (null==commands) throw new PropertiesException( 198 PropertiesException.MESSAGE + key); 199 200 return commands.getProperty(key); 201 202 } 203 204 205 /** 206 * Set the Properties file to be used for SQL commands. 207 * This can be called by main or in a servlet.init 208 * method at startup. If called more than once, the 209 * new commands are added to the existing store. 210 * If keys clash,the last one wins. 211 */ 212 public static final void init(Properties _commands) { 213 214 if (null==commands) { 215 commands = _commands; 216 } 217 else { 218 commands.putAll(_commands); 219 } 220 } 221 222 223 // ----------------------------------------------------------- Base Properties 224 225 /** 226 * [:TODO: Javadoc] 227 */ 228 public final static String INSERT = "insert"; 229 230 231 /** 232 * [:TODO: Javadoc] 233 */ 234 public final static String UPDATE = "update"; 235 236 237 /** 238 * [:TODO: Javadoc] 239 */ 240 public final static String RETRIEVE = "retrieve"; 241 242 243 /** 244 * [:TODO: Javadoc] purge 245 */ 246 public final static String DELETE = "delete"; 247 248 249 /** 250 * [:TODO: Javadoc] 251 */ 252 public final static String RESTORE = "restore"; 253 254 255 /** 256 * [:TODO: Javadoc] delete 257 */ 258 public final static String RECYCLE = "recycle"; 259 260 261 /** 262 * [:TODO: Javadoc] 263 */ 264 public final static String TABLE = "table"; 265 266 267 /** 268 * [:TODO: Javadoc] 269 */ 270 public final static String PARAMS = DOT + "params"; 271 272 273 /** 274 * A unique identifier for this StorageBean's 275 * commands. 276 */ 277 private String prefix = null; 278 279 280 // See interface for Javadoc 281 public String getPrefix() { 282 return prefix; 283 } 284 285 286 // See interface for Javadoc 287 public void setPrefix(String prefix) { 288 this.prefix = prefix; 289 } 290 291 292 /** 293 * The array of parameters required by the 294 * insert and update commands for this object. 295 */ 296 private Object[] parameters = null; 297 298 299 /** 300 * Return the runtime parameters for the given command. 301 * 302 * The comma-delimited list of parameter properties can be provided 303 * as a ${command}.params element in the command resource. 304 * <code>getParameters</code> will automatically retrieve the *.params element 305 * and use it to create an array of the runtime values for each parameter. 306 * The sequence of runtime values can then be merged with a prepared 307 * statement (the command). 308 * Since the parameters are inserted into the command by position, 309 * the column names and parameter names do not need to match. 310 * @exception ResourceException if the command resource or command cannot 311 * be found. 312 */ 313 public Object[] getParameters(String command) throws ResourceException { 314 315 if (null==command) { 316 if ((null==parameters) && (null!=paramList)) { 317 return paramList.toArray(); 318 } 319 return parameters; 320 } 321 322 // Lookup parameters for command ( * + .params) 323 String paramToken = command + PARAMS; 324 String params = lookup(paramToken); 325 326 if (null==params) { 327 throw new PropertiesException( 328 PropertiesException.MESSAGE + paramToken); 329 } 330 else { 331 String[] tokens = ConvertUtils.tokensToArray(params,PARAM_SEP); 332 Object[] values = new Object[tokens.length]; 333 try { 334 for (int i=0; i<values.length; i++) { 335 values[i] = BeanUtils.getProperty(this,tokens[i]); 336 } 337 } 338 catch (Exception e) { 339 throw new PropertiesException( 340 PropertiesException.MESSAGE + params); 341 } 342 343 return values; 344 } 345 } 346 347 348 // See interface for Javadoc 349 public void setParameters(Object[] parameters) { 350 this.parameters = parameters; 351 } 352 353 354 /** 355 * The list of parameters required by the 356 * insert and update commands for this object. 357 */ 358 private List paramList = null; 359 360 361 /** 362 * Return the vparamList or parameters field. 363 * If both are null, return an empty list. 364 */ 365 private List paramListDefault() throws ResourceException { 366 367 List list = paramList; 368 if (null==list) { 369 // Start with empty list 370 list = new java.util.ArrayList(); 371 // Add array parameters, if any 372 Object[] array = getParameters(null); 373 if (null!=array) { 374 for (int i =0; i<array.length; i++) { 375 list.add(array[i]); 376 } 377 } 378 } 379 return list; 380 381 } 382 383 384 /** 385 * Default separator character for list of parameters [","] (comma). 386 */ 387 public static final String PARAM_SEP = ","; 388 389 390 /** 391 * Return the runtime parameters for the given command. 392 * 393 * The comma-delimited list of parameter properties can be provided 394 * as a ${command}.params element in the command resource. 395 * <code>getParameters</code> will automatically retrieve the *.params element 396 * and use it to create a list of the runtime values for each parameter. 397 * The sequence of runtime values can then be merged with a prepared 398 * statement (the command). 399 * Since the parameters are inserted into the command by position, 400 * the column names and parameter names do not need to match. 401 * @exception ResourceException if the command resource or command cannot 402 * be found. 403 */ 404 public List getParamList(String command) throws ResourceException { 405 406 // If no command, return the list or array field 407 if (null==command) return paramListDefault(); 408 409 List values = new java.util.ArrayList(); 410 // Lookup parameters for command ( * + .params) 411 String paramToken = command + PARAMS; 412 String params = lookup(paramToken); 413 if (null==params) { 414 throw new PropertiesException( 415 PropertiesException.MESSAGE + paramToken); 416 } 417 else { 418 // Tokenize into list/iterator (:TODO: Cache?) (:FIXME: List better than array?) 419 Iterator tokens = ConvertUtils.tokensToList(params,PARAM_SEP).iterator(); 420 // Get the runtime property for each parameter (token) 421 try { 422 while (tokens.hasNext()) { 423 values.add(BeanUtils.getProperty(this,(String)tokens.next())); 424 } 425 } 426 catch (Exception e) { 427 throw new PropertiesException( 428 PropertiesException.MESSAGE + params); 429 } 430 } 431 return values; 432 } 433 434 435 // See interface for Javadoc 436 public void setParamList(List paramList) { 437 this.paramList = paramList; 438 } 439 440 441 /** 442 * The marked status of the record. 443 * <p> 444 * Records to be deleted are marked and may be 445 * restored before they are removed from the 446 * database. 447 * The default value is "1" - nominal. 448 */ 449 private Short marked = ConvertUtils.SHORT_ONE; 450 451 452 /** 453 * Return the marked status. 454 * <p> 455 * @return the marked status 456 */ 457 public Short getMarked() { 458 return (this.marked); 459 } 460 461 462 /** 463 * Set the marked status. 464 * @param marked The new marked status 465 */ 466 public void setMarked(Short marked) { 467 this.marked = marked; 468 } 469 470 471 // ------------------------------------------------------------ Public Methods 472 473 474 // See interface for JavaDoc 475 public void populate(Map parameters) throws Exception { 476 477 if (parameters!=null) { 478 BeanUtils.copyProperties(this,parameters); 479 } 480 481 } // end populate 482 483 484 // ------------------------------------------------------------ Create Methods 485 486 487 // See interface for JavaDoc 488 public void executeUpdate(String command) 489 throws ResourceException { 490 491 try { 492 493 int result = StatementUtils.executeUpdate( 494 null,lookup(command),getParameters(command)); 495 496 } 497 catch (SQLException e) { 498 throw new ResourceException(e); 499 } 500 501 } // end executeUpdate 502 503 504 public void executeUpdateRoot(String command) 505 throws ResourceException { 506 507 try { 508 509 int result = StatementUtils.executeUpdate( 510 null,lookupRoot(command)); 511 512 } 513 catch (SQLException e) { 514 throw new ResourceException(e); 515 } 516 517 } // end executeUpdate 518 519 // ----------------------------------------------------------- Retrieval Methods 520 521 522 // Convenience method 523 public int count( 524 String command) 525 throws ResourceException { 526 527 Integer result = null; 528 try { 529 result = (Integer) StatementUtils.getColumn( 530 null, 531 1, 532 lookup(command) 533 ); 534 } 535 catch (SQLException e) { 536 throw new ResourceException(e); 537 } 538 return result.intValue(); 539 } 540 541 542 // See interface for JavaDoc 543 public int count( 544 String command, 545 Object parameter) 546 throws ResourceException { 547 548 Integer result = null; 549 try { 550 result = (Integer) StatementUtils.getColumn( 551 null, 552 1, 553 lookup(command), 554 parameter 555 ); 556 } 557 catch (SQLException e) { 558 throw new ResourceException(e); 559 } 560 return result.intValue(); 561 } 562 563 564 565 // See interface for JavaDoc 566 public boolean findElement( 567 Object target, 568 String command, 569 Object key) throws ResourceException { 570 571 boolean found = false; 572 573 try { 574 575 found = StatementUtils.getElement(null,target, 576 lookup(command),key); 577 578 } 579 catch (SQLException e) { 580 throw new ResourceException(e); 581 } 582 583 return found; 584 585 } // end findElement 586 587 588 /** 589 * Convenience method that calls 590 * <code>findCollection(Object,String,Object[])</code> 591 * with appropriate parameters. 592 */ 593 public Collection findCollection(Object target, 594 String command) throws ResourceException { 595 596 try { 597 598 return StatementUtils.getCollection(null, 599 target,lookup(command)); 600 601 } 602 catch (SQLException e) { 603 throw new ResourceException(e); 604 } 605 606 } // end findCollection 607 608 609 /** 610 * Convenience method that calls 611 * <code>findCollection(Object,String,Object[])</code> 612 * with appropriate parameters. 613 */ 614 protected final Collection findCollection(Object target, 615 String command, int parameter) throws ResourceException { 616 617 618 try { 619 620 return StatementUtils.getCollection(null, 621 target,lookup(command),parameter); 622 623 } 624 catch (SQLException e) { 625 throw new ResourceException(e); 626 } 627 } // end findCollection 628 629 630 631 /** 632 * Convenience method that calls 633 * <code>findCollection(Object,String,Object[])</code> 634 * with appropriate parameters. 635 */ 636 protected final Collection findCollection(Object target, 637 String command, Object parameter) throws ResourceException { 638 639 try { 640 641 return StatementUtils.getCollection(null, 642 target,lookup(command),parameter); 643 644 } 645 catch (SQLException e) { 646 throw new ResourceException(e); 647 } 648 649 } // end findCollection 650 651 652 // See interface for JavaDoc 653 public Collection findCollection(Object target, 654 String command, Object[] parameters) throws ResourceException { 655 656 try { 657 658 return StatementUtils.getCollection(null, 659 target,lookup(command),parameters); 660 661 } 662 catch (SQLException e) { 663 throw new ResourceException(e); 664 } 665 666 } // end findCollection 667 668 669 // See interface for JavaDoc 670 public Collection findByProperty( 671 Object target, 672 String property, 673 String value) throws ParameterException, PopulateException, 674 ResourceException { 675 676 return SearchUtils.getCollection(target, 677 Engine.getHits( 678 Engine.getQuery(value,property))); 679 680 } // end findByProperty 681 682 683 // ================================================================ UD Methods 684 685 /** 686 * The storageKey field, if needed. 687 * <p> 688 * Many subclasses may choose to ingore this field and 689 * use the storageKey property as a wrapper around 690 * their own field of a specific type (e.g. 691 * an Integer primaryKey property). 692 */ 693 private Object storageKey = null; 694 695 696 // See interface for JavaDoc 697 public Object getStorageKey() { 698 return this.storageKey; 699 } 700 701 702 // See interface for JavaDoc 703 public void setStorageKey(Object storageKey) { 704 this.storageKey = storageKey; 705 } 706 707 /** 708 * The timestamp of the last edit. 709 * <p> 710 * This can be checked against the edited 711 * timestamp on the record in storage 712 * to see if anyone else has alreaded 713 * edited the record. 714 */ 715 private Timestamp modified = ConvertUtils.NULL_TIMESTAMP; 716 717 /** 718 * Return the edited timestamp. 719 * <p> 720 * @return the edited timestamp. 721 */ 722 public Timestamp getModified() { 723 return (this.modified); 724 } 725 726 727 /** 728 * Set the edited timestamp. 729 * @param edited The new edited timestamp. 730 */ 731 public void setModified(Timestamp modified) { 732 this.modified = modified; 733 } 734 735 736 /** 737 * Check to see if another modified timetamp 738 * matches the one for this instance. 739 * Returns true if the timestamps match. 740 * @returns true if the timestamps match. 741 * @param edited The new edited timestamp. 742 */ 743 public boolean isCurrent(Timestamp modified) { 744 return (modified!=getModified()); 745 } 746 747 748 /** 749 * [:TODO: Javadoc] 750 */ 751 private int resultCode = 0; 752 753 754 // See interface for JavaDoc 755 public int getResultCode() { 756 return resultCode; 757 } 758 759 760 // See interface for JavaDoc 761 public void setResultCode(int resultCode) { 762 this.resultCode = resultCode; 763 } 764 765 766 /** 767 * [:TODO: Javadoc] 768 */ 769 private Object result = this; 770 771 772 // See interface for JavaDoc 773 public Object getResult() { 774 return result; 775 } 776 777 778 // See interface for JavaDoc 779 public void setResult(Object result) { 780 this.result = result; 781 } 782 783 784 // --------------------------------------------------------------------- store 785 786 787 /** 788 * If timestamp is null (or ConvertUtils.NULL_TIMESTAMP), 789 * set our modified property to the current time. 790 * This emulates how MySQL treats the first null Timestamp in a record. 791 */ 792 public void fixModified() { 793 Timestamp modified = getModified(); 794 if ((null==modified) || (ConvertUtils.NULL_TIMESTAMP==modified)) { 795 setModified(new Timestamp(System.currentTimeMillis())); 796 } 797 } 798 799 800 public int updateResultCode(String command) throws ResourceException { 801 802 int result = 0; 803 try { 804 805 result = StatementUtils.executeUpdate( 806 null,lookup(command),getParameters(command)); 807 808 } 809 catch (SQLException e) { 810 throw new ResourceException(e); 811 } 812 813 return result; 814 } 815 816 // see interface for Javadoc 817 public Object update(Object parameters) throws Exception { 818 819 populate((Map) parameters); 820 821 String command = getParameter(); 822 823 fixModified(); 824 setResultCode(updateResultCode(command)); 825 826 String message = null; 827 if (isNew()) message = Tokens.DATA_RECORD_INSERTED; 828 else message = Tokens.DATA_RECORD_UPDATED; 829 830 ProcessResult result = new ProcessResultBase(getResult()); 831 result.addMessage(message); 832 result.addMessage(getStorageKey()); 833 result.setSingleForm(true); 834 return result; 835 } 836 837 838 public ProcessResult elementResult(String command) throws Exception { 839 840 boolean found = false; 841 try { 842 843 found = StatementUtils.getElement(null,this, 844 lookup(command),getParameters(command)); 845 846 } 847 catch (SQLException e) { 848 throw new ResourceException(e); 849 } 850 851 if (found) { 852 853 setResult(this); 854 setResultCode(1); 855 856 } 857 else { 858 setResultCode(0); 859 } 860 861 ProcessResult result = new ProcessResultBase(this); 862 result.setSingleForm(true); 863 return result; 864 } 865 866 867 /** 868 * Retrieve an element (record) from storage. 869 * The element is retrieved is determined by what command 870 * has been set to the parameter property. 871 * <P> 872 * This signature is designed for compatibilty with 873 * the Executable interface. 874 */ 875 public Object element(Object command) throws Exception { 876 877 populate((Map) command); 878 879 return elementResult(getParameter()); 880 881 } 882 883 884 public Object collectionResult(String command) throws Exception { 885 886 Collection result = null; 887 888 try { 889 890 result = StatementUtils.getCollection(null, 891 this,lookup(command),getParameters(command)); 892 893 } 894 catch (SQLException e) { 895 throw new ResourceException(e); 896 } 897 898 setResult(result); 899 900 return new ProcessResultBase(result); 901 902 } 903 904 905 /** 906 * Retrieve a collection of objects from storage. 907 * The objects retrieved is determined by what command 908 * has been set to the parameter property. 909 * <P> 910 * This signature is designed for compatibilty with 911 * the Executable interface. 912 */ 913 public Object collection(Object parameters) throws Exception { 914 915 populate((Map) parameters); 916 917 return collectionResult(getParameter()); 918 919 } 920 921 // --------------------------------------------------------------------- store 922 923 /** 924 * [:TODO: Javadoc] 925 */ 926 public static String KEYS_NEXT = "keys.next"; 927 928 929 /** 930 * [:TODO: Javadoc] 931 */ 932 public static String KEYS_INC = "keys.inc"; 933 934 935 // See interface for JavaDoc 936 public boolean isNew() { 937 Object key = getStorageKey(); 938 return ((null==key) || (blankValue(key.toString()))); 939 } 940 941 942 // See interface for JavaDoc 943 // @todo Refactor to use fixed-length high/low String as key. 944 public Object createKey(String keyName) 945 throws ResourceException { 946 947 Object result = null; 948 949 try { 950 951 result = StatementUtils.createKey( 952 null, 953 1, 954 lookupRoot(KEYS_NEXT), 955 lookup(keyName), 956 lookupRoot(KEYS_INC) 957 ); 958 } 959 960 catch (SQLException e) { 961 throw new ResourceException(e); 962 } 963 964 return result; 965 966 } // end createKey() 967 968 969 // See interface for JavaDoc 970 public void allocateKey() throws Exception { 971 972 setStorageKey(createKey(TABLE)); 973 974 } 975 976 977 // see interface for Javadoc 978 // INSERT The name of the insert command 979 // UPDATE The name of the delete command 980 public void store() throws Exception { 981 982 boolean isInsert = isNew(); 983 String token = null; 984 if (isInsert) { 985 token = INSERT; 986 allocateKey(); 987 } 988 else { 989 token = UPDATE; 990 } 991 992 String command = lookup(token); 993 994 Timestamp modified = getModified(); 995 if ((null==modified) || (ConvertUtils.NULL_TIMESTAMP==modified)) { 996 setModified(new Timestamp(System.currentTimeMillis())); 997 } 998 999 // :FIXME: Way to get remoteNode 1000 1001 int result = 0; 1002 try { 1003 1004 result = StatementUtils.executeUpdate( 1005 null,command,getParameters(token)); 1006 1007 } 1008 catch (SQLException e) { 1009 throw new ResourceException(e); 1010 } 1011 setResultCode(result); 1012 1013 } 1014 1015 1016 /** 1017 * Commit record to storage. 1018 * If storageKey is null, new storage for this object is created. 1019 * Otherwise, an existing object is updated. 1020 * @return ProcessResult with messages and this object as data 1021 * @exception ResourceException if data access error occurs 1022 @ @parameters The properties to use with operation 1023 * 1024 */ 1025 public Object store(Object parameters) throws Exception { 1026 1027 populate((Map) parameters); 1028 1029 String message = null; 1030 if (isNew()) message = Tokens.DATA_RECORD_INSERTED; 1031 else message = Tokens.DATA_RECORD_UPDATED; 1032 1033 store(); 1034 1035 ProcessResult result = new ProcessResultBase(getResult()); 1036 result.addMessage(message); 1037 result.addMessage(getStorageKey()); 1038 result.setSingleForm(true); 1039 return result; 1040 } 1041 1042 1043 // ------------------------------------------------------------------ retrieve 1044 1045 // see interface for Javadoc 1046 public void retrieve() throws Exception { 1047 1048 boolean found = findElement(this,RETRIEVE,getStorageKey()); 1049 1050 if (found) { 1051 1052 setResult(this); 1053 setResultCode(1); 1054 1055 } 1056 else { 1057 setResultCode(0); 1058 } 1059 1060 } 1061 1062 // see interface for Javadoc 1063 public Object retrieve(Object parameters) throws Exception { 1064 1065 populate((Map) parameters); 1066 Object key = getStorageKey(); 1067 if (null==key) { 1068 throw new ParameterException(); 1069 } 1070 1071 retrieve(); 1072 int resultCode = getResultCode(); 1073 1074 ProcessResult result = new ProcessResultBase(this); 1075 if (0==resultCode) { 1076 result.addMessage(Tokens.DATA_ACCESS_EMPTY); 1077 } 1078 else { 1079 result.addMessage(Tokens.DATA_RECORD_RETRIEVED); 1080 } 1081 result.addMessage(key); 1082 result.setSingleForm(true); 1083 1084 return result; 1085 1086 } // end retrieve 1087 1088 1089 // -------------------------------------------------------------------- delete 1090 1091 1092 // see interface for Javadoc 1093 public void delete() throws Exception { 1094 1095 retrieve(); 1096 int result = getResultCode(); 1097 1098 if (0!=result) { 1099 1100 try { 1101 1102 // Mark as deleted 1103 result = StatementUtils.executeUpdate(null, 1104 lookup(DELETE),getStorageKey()); 1105 } 1106 1107 catch (SQLException e) { 1108 throw new ResourceException(e); 1109 } 1110 1111 setResultCode(result); 1112 } 1113 1114 } 1115 1116 1117 /** 1118 * [:TODO: Javadoc] 1119 */ 1120 public Object delete(Object parameters) throws Exception { 1121 1122 populate((Map) parameters); 1123 Object key = getStorageKey(); 1124 if (null==key) { 1125 throw new ParameterException(); 1126 } 1127 1128 delete(); 1129 int resultCode = getResultCode(); 1130 1131 ProcessResult result = new ProcessResultBase(this); 1132 if (0==resultCode) { 1133 result.addMessage(Tokens.DATA_ACCESS_EMPTY); 1134 } 1135 else { 1136 result.addMessage(Tokens.DATA_RECORD_DELETED); 1137 } 1138 result.addMessage(key); 1139 result.setSingleForm(true); 1140 1141 return result; 1142 1143 } // end delete 1144 1145 1146 // -------------------------------------------------------------------- recycle 1147 1148 1149 // see interface for Javadoc 1150 public void recycle() throws Exception { 1151 1152 retrieve(); 1153 int result = getResultCode(); 1154 1155 if (0!=result) { 1156 1157 try { 1158 1159 // Mark as recycled 1160 result = StatementUtils.executeUpdate(null, 1161 lookup(RECYCLE),getStorageKey()); 1162 } 1163 1164 catch (SQLException e) { 1165 throw new ResourceException(e); 1166 } 1167 1168 setResultCode(result); 1169 } 1170 1171 } 1172 1173 1174 // see interface for Javadoc 1175 public Object recycle(Object parameters) throws Exception { 1176 1177 populate((Map) parameters); 1178 Object key = getStorageKey(); 1179 if (null==key) { 1180 throw new ParameterException(); 1181 } 1182 1183 recycle(); 1184 int resultCode = getResultCode(); 1185 1186 ProcessResult result = new ProcessResultBase(this); 1187 if (resultCode==0) { 1188 result.addMessage(Tokens.DATA_ACCESS_EMPTY); 1189 } 1190 else { 1191 result.addMessage(Tokens.DATA_RECORD_RECYCLED); 1192 } 1193 result.addMessage(key); 1194 result.setSingleForm(true); 1195 1196 return result; 1197 1198 } // end recycle 1199 1200 1201 // ------------------------------------------------------------------- restore 1202 1203 /** 1204 * Unmark entry for deletion. 1205 * Returns copy of restored entry in target parameter. 1206 * 1207 * @return 0 if fails 1208 * @exception ResourceException if data access error occurs 1209 * @param target Bean to hold copy of record being unmarked 1210 * @param article Primary key of record to unmark 1211 */ 1212 public void restore() throws Exception { 1213 1214 int result = 0; 1215 1216 try { 1217 1218 result = StatementUtils.executeUpdate(null, 1219 lookup(RESTORE),getStorageKey()); 1220 1221 } 1222 catch (SQLException e) { 1223 throw new ResourceException(e); 1224 } 1225 1226 setResultCode(result); 1227 1228 } // end restore 1229 1230 1231 /** 1232 * Update indicated entry in data storage. 1233 * Return confirmation message in a ProcessResult object. 1234 * 1235 * @param parameters The map or other object to use with this 1236 * operation 1237 * @throws ParameterException if article not found in parameters 1238 * @throws ResourceException if SQLException or other data exception 1239 */ 1240 public Object restore(Object parameters) throws Exception { 1241 1242 populate((Map) parameters); 1243 Object key = getStorageKey(); 1244 if (null==key) { 1245 throw new ParameterException(); 1246 } 1247 1248 restore(); 1249 int resultCode = getResultCode(); 1250 1251 ProcessResult result = new ProcessResultBase(this); 1252 if (0==resultCode) { 1253 result.addMessage(Tokens.DATA_ACCESS_EMPTY); 1254 } 1255 else { 1256 result.addMessage(Tokens.DATA_RECORD_RESTORED); 1257 } 1258 result.addMessage(key); 1259 result.setSingleForm(true); 1260 1261 return result; 1262 1263 } // end restore 1264 1265 } // end StorageBeanBase 1266