Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/RuntimeCollective/questionnaire/bean/ClusterSafeQuestionnaire.java


1   /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/questionnaire/bean/ClusterSafeQuestionnaire.java,v 1.5 2003/10/13 11:29:27 miles Exp $
2    * $Revision: 1.5 $
3    * $Date: 2003/10/13 11:29:27 $
4    *
5    * ====================================================================
6    *
7    * Josephine : http://www.runtime-collective.com/josephine/index.html
8    *
9    * Copyright (C) 2003 Runtime Collective
10   *
11   * This product includes software developed by the
12   * Apache Software Foundation (http://www.apache.org/).
13   *
14   * This library is free software; you can redistribute it and/or
15   * modify it under the terms of the GNU Lesser General Public
16   * License as published by the Free Software Foundation; either
17   * version 2.1 of the License, or (at your option) any later version.
18   *
19   * This library is distributed in the hope that it will be useful,
20   * but WITHOUT ANY WARRANTY; without even the implied warranty of
21   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   * Lesser General Public License for more details.
23   *
24   * You should have received a copy of the GNU Lesser General Public
25   * License along with this library; if not, write to the Free Software
26   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27   *
28   */
29  
30  package com.RuntimeCollective.questionnaire.bean;
31  
32  import com.RuntimeCollective.questionnaire.QuestionnaireException;
33  import com.RuntimeCollective.questionnaire.bean.Question;
34  import com.RuntimeCollective.questionnaire.bean.QuestionnaireLink;
35  import com.RuntimeCollective.questionnaire.bean.UserAnswers;
36  import com.RuntimeCollective.sitemap.bean.Publishable;
37  import com.RuntimeCollective.sitemap.bean.SimplePublishable;
38  import com.RuntimeCollective.webapps.RuntimeParameters;
39  import com.RuntimeCollective.webapps.RuntimeDataSource;
40  import com.RuntimeCollective.webapps.bean.User;
41  
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.ArrayList;
45  import java.util.Collections;
46  import java.sql.SQLException;
47  
48  /**
49   * An extension of Questionnaire that is (I really hope) cluster-safe
50   * (i.e. works with the SynchronizedEBS).
51   *
52   * @version $Id: ClusterSafeQuestionnaire.java,v 1.5 2003/10/13 11:29:27 miles Exp $
53   */
54  public class ClusterSafeQuestionnaire extends Questionnaire {
55  
56  
57      /** A list of UserAnswers added to this Questionnaire since the last save. */
58      private List unsaved;
59  
60      /** Save this bean to the database. */
61      public void save() {
62  
63    // Save the actual questionnaire
64    super.save();
65  
66    // Check all unsaved
67    try {
68        ArrayList updates = new ArrayList();
69        String[] updates_array;
70  
71        int i=0;
72        while (i<unsaved.size()) {
73      Integer[] oneUnsaved = (Integer[]) unsaved.get(i);
74  
75      // Is there now a saved UserAnswers with this id?  (belonging to no-one, possibly)
76      int[] ids = RuntimeDataSource.queryInts("select 1 from quest_useranswers where id = "+oneUnsaved[0]);
77  
78      // If so, save the mapping, and remove it from unsaved
79      if (ids != null && ids.length > 0) {
80          updates.add((new StringBuffer(105)).append("update quest_useranswers set answered_questionnaire_id = "+id).append(", position_no = "+i).append(" where id = "+oneUnsaved[0]).toString());
81          RuntimeParameters.logDebug(this, "Save: don't need "+oneUnsaved[0]);
82          unsaved.remove(i);
83      } else {
84          i++;
85      }
86        }
87  
88        // Do the updates
89        if (!updates.isEmpty()) {
90      updates_array = new String[updates.size()];
91      for (int j=0; j<updates.size(); j++)
92          updates_array[j] = (String) updates.get(j);
93      RuntimeDataSource.update(updates_array);
94        }
95  
96  
97    } catch (SQLException e) {
98        throw new QuestionnaireException("ClusterSafeQuestionnaire could not save() : "+e);
99    }
100 
101     }
102 
103 
104     /** Add a UserAnswers to this Questionnaire
105      * @param userAnswers, the UserAnswers to add
106      */
107     public void addUserAnswers(UserAnswers userAnswers) {
108   if (userAnswers != null) {
109       Integer provisionalId = getProvisionalPosition();
110       unsaved.add( new Integer[]{ idFromUA(userAnswers),
111           provisionalId });
112   }
113     }
114 
115     /** Remove a UserAnswers from this Questionnaire
116      * @param userAnswers, the UserAnswers to remove
117      */
118     public void removeUserAnswers(UserAnswers userAnswers) {
119   if (userAnswers == null)
120       return;
121 
122   // remove from unsaved, if present
123   Integer uaId = idFromUA(userAnswers);
124 
125   int i=0;
126   while (i<unsaved.size()) {
127       Integer[] oneUnsaved = (Integer[]) unsaved.get(i);
128       if (uaId == oneUnsaved[0]) {
129     RuntimeParameters.logDebug(this, "Removing "+oneUnsaved[0]+" from unsaved");
130     unsaved.remove(i);
131       } else {
132     i++;
133       }
134   }
135     }
136 
137 
138     /** Get a UserAnswers from this Questionnaire
139      * @param position, the index of the UserAnswers to get
140      * @return the UserAnswers at that index, or null if there is none
141      */
142     public UserAnswers getUserAnswers(int position) {
143   int uaId = -1;
144   UserAnswers oneUA = null;
145 
146   // look in unsaved first
147   int i=0;
148   while (i<unsaved.size()) {
149       Integer[] oneUnsaved = (Integer[]) unsaved.get(i);
150       if ( position == oneUnsaved[1].intValue()) {
151     uaId = oneUnsaved[0].intValue();
152       } else {
153     i++;
154       }
155   }
156 
157   // no? try the database
158   if (uaId == -1) {
159       try {
160     int[] ids = RuntimeDataSource.queryInts("select 1 from quest_useranswers where answered_questionnaire_id = "+getId()
161               +" and position = "+position);
162     if (ids != null && ids.length > 0) {
163         uaId = ids[0];
164     }
165       } catch (SQLException e) {
166     e.printStackTrace(System.out);
167     RuntimeParameters.logError(this, "getUserAnswers: SQL error getting "+uaId+": "+e);
168       }
169   }
170 
171   // try building the UA, if we have one
172   if (uaId != -1) {
173       try {
174     oneUA = (UserAnswers) RuntimeParameters.getStore().get(UserAnswers.class.getName(), uaId);
175       } catch (RuntimeException e) {
176     e.printStackTrace(System.out);
177     RuntimeParameters.logError(this, "getUserAnswers: error getting "+uaId+": "+e);
178       }
179   }
180 
181   return oneUA;
182     }
183 
184 
185     /** Set a UserAnswers in this Questionnaire.
186      * (This adds it to the "unsaved" list.)
187      * @param position, the index where the UserAnswers will be
188      * @param userAnswers, the UserAnswers to put in that position
189      */
190     public void setUserAnswers(int position, UserAnswers userAnswers) {
191   unsaved.add(new Integer[]{ idFromUA(userAnswers),
192            new Integer(position) });
193     }
194 
195 
196     /** Get the (first) index of a UserAnswers in this Questionnaire
197      * @param userAnswers, the UserAnswers to look for
198      * @return an int, the position of the UserAnswers, or -1 if not found
199      */
200     public int getIndexOfUserAnswers(UserAnswers userAnswers) {
201   if (userAnswers == null)
202       return -1;
203 
204   // check db
205   try {
206       int pos[] = RuntimeDataSource.queryInts("select position_no from quest_useranswers where answered_questionnaire_id = "+getId()
207                 +"and id = "+userAnswers.getId());
208       if (pos != null && pos.length>0) {
209     return pos[0];
210       }
211   } catch (SQLException e) {
212       e.printStackTrace(System.out);
213       RuntimeParameters.logError(this, "getIndexOfUserAnswers: SQL error checking db: "+e);
214   }
215 
216 
217   // not there? check unsaved
218   Integer uaId = idFromUA(userAnswers);
219 
220   for (int i=0; i<unsaved.size(); i++) {
221       Integer[] oneUnsaved = (Integer[]) unsaved.get(i);
222       if (uaId == oneUnsaved[0]) {
223     RuntimeParameters.logDebug(this, "Found "+uaId+" in unsaved!");
224 
225     // Check provisional position, and return
226     return updateProvisionalPosition(i);
227       }
228   }
229 
230   return -1;
231     }
232 
233 
234     /** Get all UserAnswers from this Questionnaire
235      * @return an (ordered) Iterator of UserAnswers
236      */
237     public Iterator getAllUserAnswers() {
238   return getAllUserAnswersAsList().iterator();
239     }
240 
241     /**
242      * List version of getAllUserAnswers().
243      * <p>
244      * Adding to / removing from  this list will have no effect
245      * on the underlying Questionnaire.  It is a throwaway list.
246      */
247     protected List getAllUserAnswersAsList() {
248   ArrayList allUAs = new ArrayList();
249 
250   // add all in the db
251   try {
252       int[] rows = RuntimeDataSource.queryInts("select id from "+UserAnswers.DATABASE_TABLE+" where answered_questionnaire_id = "+id+" order by position_no");
253       for (int i=0; i<rows.length; i++) {
254     RuntimeParameters.logDebug(this, "getAllUserAnswers(): from db: "+rows[i]);
255     allUAs.add(uaFromId(new Integer(rows[i])));
256       }
257   } catch (SQLException e) {
258       e.printStackTrace(System.out);
259       RuntimeParameters.logError(this, "getAllUserAnswersAsList: SQL error checking db: "+e);
260   }
261   // add all unsaved
262   for (int i=0; i<unsaved.size(); i++) {
263       Integer[] oneUnsaved = (Integer[]) unsaved.get(i);
264       RuntimeParameters.logDebug(this, "getAllUserAnswers(): from unsaved: "+oneUnsaved[0]);
265       allUAs.add(uaFromId(oneUnsaved[0]));
266   }
267 
268   return allUAs;
269     }
270 
271     /** Get all member UserAnswers OR anon UserAnswers
272      * @param boolean, membersOnly
273      * @return an (ordered) iterator of either anon or member UserAnswers
274      */
275     public Iterator getAllUserAnswers(boolean membersOnly) {
276   ArrayList ofUserAnswers = new ArrayList();
277   UserAnswers temp;
278 
279   Iterator allUAs = getAllUserAnswers();
280 
281   if (!membersOnly) {
282       while (allUAs.hasNext()) {
283     temp = (UserAnswers) allUAs.next();
284     if (temp.getAnsweringUser() == null) {
285         ofUserAnswers.add(temp);
286     }
287       }
288   } else {
289       while (allUAs.hasNext()) {
290     temp = (UserAnswers) allUAs.next();
291     if (temp.getAnsweringUser() != null) {
292         ofUserAnswers.add(temp);
293     }
294       }
295   }
296   return ofUserAnswers.iterator();
297     }
298 
299 
300     /** Get all UserAnswers from a given User for this Questionnaire
301      * @param user, the user whose UserAnswers we want
302      * @return an (ordered) Iterator of UserAnswers
303      */
304     public Iterator getAllUserAnswersForUser(User user) {
305   ArrayList result = new ArrayList();
306 
307   if (user != null) {
308       UserAnswers temp;
309 
310       Iterator allUAs = getAllUserAnswers();
311       while (allUAs.hasNext()) {
312     temp = (UserAnswers) allUAs.next();
313     if ((temp.getAnsweringUser() != null) &&
314         (temp.getAnsweringUser().getId() == user.getId()))
315         result.add(temp);
316       }
317   }
318 
319   return result.iterator();
320     }
321 
322 
323     /** Get the number of votes, ie the number of UserAnswers
324      * @return an int
325      */
326     public int getNumberOfVotes() {
327   return getAllUserAnswersAsList().size();
328     }
329 
330 
331     /** Get the number of anonomous votes, ie the number of UsersAnswers where the userId is -1
332      * @return an int
333      */
334     public int getNumberOfAnonVotes() {
335   int result = 0;
336   UserAnswers temp;
337 
338   Iterator allUAs = getAllUserAnswers();
339   while (allUAs.hasNext()) {
340       temp = (UserAnswers) allUAs.next();
341       if (temp.getAnsweringUser() == null) {
342     // this was an anon answer - the userId was -1
343     result++;
344       }
345   }
346   return result;
347     }
348 
349 
350     /**
351      * Initialise this object.
352      */
353     protected void init() {
354   unsaved = Collections.synchronizedList(new ArrayList());
355   // Clear the TheUserAnswers arrayList; it's not used
356   TheUserAnswers = new ArrayList();
357     }
358 
359     /*
360      * See superclass.
361      */
362     public ClusterSafeQuestionnaire() {
363   super();
364   init();
365     }
366 
367     /** Get a current Questionnaire from the RuntimeDataSource, given an id.
368      * @param id ID of the Questionnaire.
369      */
370     public ClusterSafeQuestionnaire(int id) {
371   super(id);
372   init();
373     }
374 
375 
376     /**
377      * Gets the next possible position for a UserAnswer,
378      * by examining the database
379      */
380     protected Integer getProvisionalPosition() {
381   int provId = 0;
382 
383   try {
384       int[] ids = RuntimeDataSource.queryInts("select max(position_no) from quest_useranswers where answered_questionnaire_id = "+getId());
385       if (ids != null && ids.length > 0) {
386     provId = ids[0] + 1;
387       }
388   } catch (SQLException e) {
389       e.printStackTrace(System.out);
390       RuntimeParameters.logError(this, "getProvisionalPosition: SQL error checking db: "+e);
391   }
392 
393   RuntimeParameters.logDebug(this, "ProvisionalId: "+provId);
394 
395   return new Integer(provId);
396     }
397 
398 
399     /**
400      * Check the provisional position for the UserAnswer stored
401      * at position <code>unsavedIndex</code> in the <code>unsaved</code>
402      * List, to make sure it hasn't been used by another UserAnswer
403      * in the meantime.  If it has, refresh it, and return it.
404      */
405     protected int updateProvisionalPosition(int unsavedIndex) {
406   Integer[] oneUnsaved = (Integer[]) unsaved.get(unsavedIndex);
407   Integer provPos = oneUnsaved[1];
408   try {
409       int[] ids = RuntimeDataSource.queryInts("select id from quest_useranswers where answered_questionnaire_id = "+getId()
410                 +" and position_no = "+provPos);
411       if (ids != null && ids.length > 0) {
412     RuntimeParameters.logDebug(this, "Prov position has been FILLED by "+ids[0]);
413     // get a new provisional id!
414     provPos = getProvisionalPosition();
415     oneUnsaved[1] = provPos;
416     //unsaved.remove(unsavedIndex);
417     //unsaved.add(unsavedIndex, oneUnsaved);
418       }
419   } catch (SQLException e) {
420       e.printStackTrace(System.out);
421       RuntimeParameters.logError(this, "updateProvisionalPosition: SQL error checking db: "+e);
422   }
423 
424   RuntimeParameters.logDebug(this, "updateProvPos: return "+provPos);
425 
426   return provPos.intValue();
427     }
428 
429     /**
430      * Returns the ID of a UserAnswers object, if indeed this object is a UserAnswers
431      * @exception ClassCastException if <code>o</code> is not a UserAnswers
432      */
433     protected Integer idFromUA(Object o) throws ClassCastException {
434   return new Integer( ((UserAnswers) o).getId());
435     }
436 
437     /**
438      * Returns a UserAnswers from an Integer object , if indeed this object is an Integer
439      * @exception ClassCastException if <code>o</code> is not a Integer
440      */
441     protected UserAnswers uaFromId(Object o) throws ClassCastException {
442   return (UserAnswers)RuntimeParameters.getStore().get(UserAnswers.class.getName(), ((Integer)o).intValue());
443     }
444 
445 }