View Javadoc

1   /*
2    * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/event/datalist/InsertEvent.java,v 1.32 2005/11/30 20:31:17 hkollmann Exp $
3    * $Revision: 1.32 $
4    * $Date: 2005/11/30 20:31:17 $
5    *
6    * DbForms - a Rapid Application Development Framework
7    * Copyright (C) 2001 Joachim Peer <joepeer@excite.com>
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2.1 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   */
23  package org.dbforms.event.datalist;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.dbforms.config.DbFormsConfig;
27  import org.dbforms.config.Field;
28  import org.dbforms.config.FieldValues;
29  import org.dbforms.config.GrantedPrivileges;
30  import org.dbforms.config.MultipleValidationException;
31  
32  import org.dbforms.event.AbstractValidationEvent;
33  import org.dbforms.event.datalist.dao.DataSourceFactory;
34  import org.dbforms.event.datalist.dao.DataSourceSessionList;
35  import org.dbforms.interfaces.DbEventInterceptorData;
36  import org.dbforms.interfaces.IDbEventInterceptor;
37  
38  import org.dbforms.util.MessageResourcesInternal;
39  import org.dbforms.util.StringUtil;
40  import org.dbforms.util.Util;
41  
42  import java.sql.Connection;
43  import java.sql.SQLException;
44  
45  import java.util.Vector;
46  
47  import java.io.UnsupportedEncodingException;
48  
49  import javax.servlet.http.HttpServletRequest;
50  
51  
52  
53  /***
54   * This event prepares and performs a SQL-Insert operation. <br>
55   * Works with new factory classes
56   *
57   * @author Henner Kollmann
58   */
59  public class InsertEvent extends AbstractValidationEvent {
60  
61  	private static Log logCat = LogFactory.getLog(InsertEvent.class.getName()); // logging category for this class
62     
63  	/***
64      * Creates a new InsertEvent object.
65      *
66      * @param tableId the table identifier
67      * @param keyId the key
68      * @param request the request object
69      * @param config the configuration object
70      */
71     public InsertEvent(Integer tableId, String keyId,
72        HttpServletRequest request, DbFormsConfig config) {
73        super(tableId.intValue(), keyId, request, config);
74     }
75  
76  
77     /***
78      * Constructor. <br>
79      * Insert actionbutton-strings is as follows: ac_insert_12_root_3 which is
80      * equivalent to: ac_insert  : insert action event 12         : table id
81      * root       : key 3          : button count used to identify individual
82      * insert buttons
83      *
84      * @param action the action string
85      * @param request the request object
86      * @param config the config object
87      */
88     public InsertEvent(String action, HttpServletRequest request,
89        DbFormsConfig config) {
90        super(StringUtil.getEmbeddedStringAsInteger(action, 2, '_'),
91           StringUtil.getEmbeddedString(action, 3, '_'), request, config);
92     }
93  
94     /***
95      * Get the FieldValues object representing the collection of FieldValue
96      * objects builded from the request parameters
97      *
98      * @return the FieldValues object representing the collection of FieldValue
99      *         objects builded from the request parameters
100     */
101 
102    // must be public because protected will break cactus testing!
103    public FieldValues getFieldValues() {
104       return getFieldValues(true);
105    }
106 
107 
108    /***
109     * Process this event.
110     *
111     * @param con the jdbc connection object
112     *
113     * @throws SQLException if any data access error occurs
114     * @throws MultipleValidationException if any validation error occurs
115     */
116    public void processEvent(Connection con) throws SQLException, MultipleValidationException {
117       // Applying given security contraints (as defined in dbforms-config xml file)
118       // part 1: check if requested privilge is granted for role
119       if (!hasUserPrivileg(GrantedPrivileges.PRIVILEG_INSERT)) {
120          String s = MessageResourcesInternal.getMessage("dbforms.events.insert.nogrant",
121                getRequest().getLocale(), new String[] {
122                   getTable().getName()
123                });
124          throw new SQLException(s);
125       }
126 
127       FieldValues fieldValues = getFieldValues();
128 
129       if (fieldValues.size() == 0) {
130          throw new SQLException("no parameters");
131       }
132 
133       DbEventInterceptorData interceptorData = new DbEventInterceptorData(getRequest(),
134             getConfig(), con, getTable());
135       interceptorData.setAttribute(DbEventInterceptorData.FIELDVALUES,
136          fieldValues);
137 
138       // process the interceptors associated to this table
139       int operation = getTable().processInterceptors(IDbEventInterceptor.PRE_INSERT,
140             interceptorData);
141 
142       if ((operation == IDbEventInterceptor.GRANT_OPERATION)
143                && (fieldValues.size() > 0)) {
144          // End of interceptor processing
145          if (!checkSufficentValues(fieldValues)) {
146             throw new SQLException("unsufficent parameters");
147          }
148 
149          // INSERT operation;
150          DataSourceSessionList ds  = DataSourceSessionList.getInstance(getRequest());
151          DataSourceFactory     qry = ds.get(getTable(), getRequest());
152 
153          boolean               own = false;
154 
155          if (qry == null) {
156             qry    = new DataSourceFactory((String) interceptorData
157                   .getAttribute(DbEventInterceptorData.CONNECTIONNAME),
158                   interceptorData.getConnection(), getTable());
159             own    = true;
160          }
161 
162          getRequest().setAttribute("forceUpdate", "true");
163          int i = qry.doInsert(interceptorData, fieldValues);
164          interceptorData.setAttribute(DbEventInterceptorData.ROWSAFFECTED, new Integer(i));
165 
166          if (own) {
167             qry.close();
168          } else {
169             ds.remove(getTable(), getRequest());
170          }
171 
172          // Show the last record inserted
173          String firstPosition = getTable().getPositionString(fieldValues);
174          // CAPIO - must encode the position as it gets decoded when read.
175          try {
176          	firstPosition = Util.encode(firstPosition, getRequest().getCharacterEncoding());
177 		 } catch (UnsupportedEncodingException ex) {
178 		    logCat.error(ex);
179 			throw new SQLException(ex.getMessage());
180 		 }
181 		 getRequest().setAttribute("firstpos_" + getTable().getId(),
182             firstPosition);
183 
184          // finally, we process interceptor again (post-insert)
185          // process the interceptors associated to this table
186          getTable().processInterceptors(IDbEventInterceptor.POST_INSERT,
187             interceptorData);
188       }
189    }
190 
191 
192    /***
193     * Check a list of conditions on the the input FieldValues object:
194     *
195     * <ul>
196     * <li>
197     * it must contains the same number of fields as the current main Table
198     * </li>
199     * <li>
200     * any autoInc field must NOT have a related FieldValue object (generated by
201     * a request parameter) because that field value must be calculated by the
202     * underlying RDBMS
203     * </li>
204     * </ul>
205     *
206     *
207     * @param fieldValues the FieldValues object containing the Field elements
208     *        to check
209     *
210     * @return true  if the  all the above conditions are true, false otherwise
211     *
212     * @throws SQLException if any check condition fails
213     */
214    private boolean checkSufficentValues(FieldValues fieldValues)
215       throws SQLException {
216       Vector fields = getTable().getFields();
217 
218       for (int i = 0; i < fields.size(); i++) {
219          Field field = (Field) fields.elementAt(i);
220 
221          // if a field is a key and if it is NOT automatically generated,
222          // then it should be provided by the user
223          if (!field.hasAutoIncSet() && field.hasIsKeySet()) {
224             if (fieldValues.get(field.getName()) == null) {
225                throw new SQLException("Field " + field.getName()
226                   + " is missing");
227             }
228          }
229          // in opposite, if a field is automatically generated by the RDBMS, we need to
230          else if (field.hasAutoIncSet()) {
231             if (fieldValues.get(field.getName()) != null) {
232                throw new SQLException("Field " + field.getName()
233                   + " should be calculated by RDBMS, remove it from the form");
234             }
235          }
236 
237          // in future we could do some other checks like NOT-NULL conditions,etc.
238       }
239 
240       return true;
241    }
242 }