Source code: com/RuntimeCollective/webapps/bean/ModeratedExtension.java
1 /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/webapps/bean/ModeratedExtension.java,v 1.8 2003/09/30 15:13:09 joe Exp $
2 * $Revision: 1.8 $
3 * $Date: 2003/09/30 15:13:09 $
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.webapps.bean;
31
32 import com.RuntimeCollective.webapps.EntityBeanStore;
33 import com.RuntimeCollective.webapps.RuntimeDataSource;
34 import com.RuntimeCollective.webapps.RuntimeParameters;
35 import com.RuntimeCollective.webapps.bean.EntityBean;
36 import com.RuntimeCollective.webapps.bean.User;
37
38 import java.sql.SQLException;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.HashMap;
42 import java.util.Iterator;
43
44
45 /**
46 * This is an extension which can be stuck to any EntityBean, and allows
47 * for the storage of moderation information for that bean.
48 * <p>
49 * Moderation is used as a mechanism for vetting content before it is
50 * displayed on the public site. This is different from the
51 * <code>Publishable</code> interface since there is no versioning or
52 * editing cycle involved. Once a moderator has approved a bean it
53 * will be public from there on.
54 * <p>
55 * Current moderation behaviour is based on <code>UserGroup</code>s, i.e.
56 * beans are assigned moderators that belong to a specific group.
57 *
58 * @version $Id: ModeratedExtension.java,v 1.8 2003/09/30 15:13:09 joe Exp $
59 */
60 public class ModeratedExtension implements EntityBean {
61
62 private static String DELETE_FROM = "delete from ";
63 private static String SELECT_DATA = "select t.moderated_bean_id, t.moderator_user_id, is_moderated, is_approved from ";
64 private static String SELECT_MAPPINGS = "select id, moderated_bean_id from ";
65 private static String WHERE_ID = " where id = ";
66 private static String WHERE_T_ID = " t where t.id = ";
67 private static String WHERE_EB_ID = " t where t.moderated_bean_id = ";
68
69
70 // -------------------- EntityBean implementation -------------------------
71
72 /** The name of the database table for this bean type. */
73 public static final String DATABASE_TABLE = "webapps_moderated";
74
75 /** This bean's id */
76 protected int id;
77
78 /**
79 * Set the unique id of this bean instance.
80 */
81 public void setId(int id) {
82 this.id = id;
83 }
84
85 /**
86 * Get the unique id of this bean instance.
87 */
88 public int getId() {
89 return id;
90 }
91
92 /**
93 * Save this bean in the database.
94 */
95 public void save() throws SQLException {
96
97 Integer beanInt = (moderatedBeanId == EntityBean.NULL_ID) ? null : new Integer(moderatedBeanId);
98 Integer extInt = (id == EntityBean.NULL_ID) ? null : new Integer(id);
99 Integer moderatorInt = (moderatorUserId == EntityBean.NULL_ID) ? null : new Integer(moderatorUserId);
100
101 RuntimeDataSource.save(id, DATABASE_TABLE,
102 new String[] { "is_moderated", "is_approved", "moderator_user_id", "moderated_bean_id" },
103 new Object[] { new Boolean(isModerated),
104 new Boolean(isApproved),
105 moderatorInt,
106 beanInt }
107 );
108
109 // update the mapping cache
110 updateMapping(beanInt, extInt);
111 }
112
113 /**
114 * Delete this bean from the database.
115 */
116 public void delete() throws SQLException {
117 RuntimeDataSource.update(DELETE_FROM+DATABASE_TABLE+WHERE_ID+id);
118
119 // update the mapping cache
120 Integer beanInt = (moderatedBeanId == EntityBean.NULL_ID) ? null : new Integer(moderatedBeanId);
121 updateMapping(beanInt, null);
122 }
123
124
125 // -------------------- ModeratedExtension specific -------------------------
126
127 /**
128 * Constructs a new blank bean with a unique id.
129 */
130 public ModeratedExtension() throws SQLException {
131 setId(RuntimeDataSource.nextId());
132 }
133
134 /**
135 * Gets a bean from the RuntimeDataSource, given an id.
136 *
137 * @param id id of the Moderated bean
138 * @exception SQLException thrown if no bean with such an id exits
139 */
140 public ModeratedExtension(int id) throws SQLException {
141 Object[] results = RuntimeDataSource.queryRow(SELECT_DATA+DATABASE_TABLE+WHERE_T_ID+id);
142 if (results.length != 4) {
143 throw new SQLException("Cannot load ModeratedExtension with id="+id+" : "
144 +results.length+" fields found in "+DATABASE_TABLE+".");
145 }
146 this.id = id;
147 if (results[0] != null)
148 moderatedBeanId = Integer.parseInt(results[0].toString());
149 else
150 moderatedBeanId = EntityBean.NULL_ID;
151 if (results[1] != null)
152 moderatorUserId = Integer.parseInt(results[1].toString());
153 else
154 moderatorUserId = EntityBean.NULL_ID;
155 if (results[2] != null)
156 isModerated = RuntimeDataSource.toboolean(results[2].toString());
157 else
158 isModerated = true;
159 if (results[3] != null)
160 isApproved = RuntimeDataSource.toboolean(results[3].toString());
161 else
162 isApproved = false;
163
164 }
165
166
167 /** The EntityBean id of the bean this bean is the moderator for. */
168 protected int moderatedBeanId = EntityBean.NULL_ID;
169
170 /** Gets themoderated bean. */
171 public EntityBean getEntityBean() {
172 return (EntityBean)RuntimeParameters.getStore().get(EntityBean.class.getName(), moderatedBeanId);
173 }
174 /** Sets the moderated bean. */
175 public void setEntityBean(EntityBean bean) {
176 if (bean == null)
177 this.moderatedBeanId = EntityBean.NULL_ID;
178 else
179 this.moderatedBeanId = bean.getId();
180 }
181
182
183 /** Is this bean moderated. */
184 protected boolean isModerated = false;
185
186 /** Gets moderation status of this bean. */
187 public boolean getIsModerated() {
188 return isModerated;
189 }
190 /** Sets moderation status of this bean. */
191 public void setIsModerated(boolean moderate) {
192 isModerated = moderate;
193 }
194
195
196 /** Has the moderator approved the bean. */
197 protected boolean isApproved = false;
198
199 /** Gets approval status of this bean. */
200 public boolean getIsApproved() {
201 return isApproved;
202 }
203 /** Sets approval status of this bean. */
204 public void setIsApproved(boolean approve) {
205 isApproved = approve;
206 }
207
208
209 /** Id of the User bean acting as moderator of this bean. */
210 protected int moderatorUserId = User.NULL_ID;
211
212 /** Gets the User for this ModeratedExtension */
213 public User getModeratorUser() {
214 if (moderatorUserId != EntityBean.NULL_ID) {
215 return (User)RuntimeParameters.getStore().get(User.class.getName(), moderatorUserId);
216 } else {
217 return null;
218 }
219 }
220 /** Sets the User for this ModeratedExtension */
221 public void setModeratorUser(User user) {
222 if (user == null)
223 this.moderatorUserId = EntityBean.NULL_ID;
224 else
225 this.moderatorUserId = user.getId();
226 }
227
228
229 // -------------------- ModeratedExtension statics -------------------------
230
231 /**
232 * Gets the ModeratedExtension for a particular bean if one exists.
233 *
234 * @param eb, the EntityBean whose ModeratedExtension we need
235 * @return an ModeratedExtension object, or null if none was found
236 */
237 public static ModeratedExtension getFor(EntityBean eb) {
238 if (eb == null) {
239 return null;
240 }
241
242 Integer extInt = (Integer) getMappingCache().get(new Integer(eb.getId()));
243 if (extInt == null) {
244 return null;
245 } else {
246 return (ModeratedExtension) RuntimeParameters.getStore().get(ModeratedExtension.class.getName(), extInt.intValue());
247 }
248 }
249
250 protected static HashMap mappingCache = null;
251
252 protected static HashMap getMappingCache() {
253 if (mappingCache == null) {
254 initMappingCache();
255 }
256 return mappingCache;
257 }
258
259 protected static void initMappingCache() {
260 try {
261 Object[][] results = RuntimeDataSource.queryRows(SELECT_MAPPINGS+DATABASE_TABLE);
262 mappingCache = new HashMap();
263 for (int i=0; i<results.length; i++) {
264 // both are Integers
265 mappingCache.put(results[i][1], results[i][0]);
266 }
267 } catch (SQLException e) {
268 RuntimeParameters.logError("ModeratedExtension", "Could not load mappings.", e);
269 e.printStackTrace();
270 }
271 }
272
273 protected static void updateMapping(Integer beanInt, Integer extInt) {
274 if (beanInt == null) {
275 return;
276 }
277
278 HashMap map = getMappingCache();
279 if (extInt == null) {
280 map.remove(beanInt);
281 } else {
282 map.put(beanInt, extInt);
283 }
284 }
285
286 /**
287 * Gets or creates the ModeratedExtension for a particular bean.
288 * <p>
289 * NOTE: newly created ModeratedExtension objects are NOT saved -
290 * you'll need to do that.
291 *
292 * @param eb, the EntityBean whose ModeratedExtension we need
293 * @return an ModeratedExtension object, or null if none was found
294 */
295 public static ModeratedExtension getOrCreateFor(EntityBean eb) {
296
297 if (eb == null) {
298 return null;
299 }
300
301 ModeratedExtension modExt = ModeratedExtension.getFor(eb);
302 if (modExt != null) {
303 return modExt;
304 }
305
306 // ok we'll need to create it
307 modExt = (ModeratedExtension)RuntimeParameters.getStore().create(ModeratedExtension.class.getName());
308 modExt.setEntityBean(eb);
309
310 // not saving it - caller is responsible!
311 return modExt;
312 }
313
314
315 /**
316 * Filter out non-approved EntityBeans from a List of EntityBean.
317 * Note this considers all the EntityBeans which don't have a
318 * ModeratedExtension as being approved (hence they *are* in the
319 * returned List).
320 *
321 * @return A List of EntityBeans
322 */
323 public static List filterOutNonApproved(List beans) {
324 if (beans != null) {
325 return ModeratedExtension.filterOutNonApproved(beans.iterator());
326 } else {
327 return new ArrayList();
328 }
329 }
330
331
332 /**
333 * Filter out non-approved EntityBeans from an Iterator of EntityBean.
334 * Note this considers all the EntityBeans which don't have a
335 * ModeratedExtension as being approved (hence they *are* in the
336 * returned List).
337 *
338 * @return A List of EntityBeans
339 */
340 public static List filterOutNonApproved(Iterator beans) {
341 List approved = new ArrayList();
342
343 if (beans != null) {
344 EntityBean bean;
345 while (beans.hasNext()) {
346 bean = (EntityBean) beans.next();
347 if (!ModeratedExtension.needApproval(bean)) {
348 // keep this one
349 approved.add(bean);
350 }
351 }
352 }
353
354 return approved;
355 }
356
357 /**
358 * Filter and keep non-approved EntityBeans from a List of EntityBean.
359 * Note this considers all the EntityBeans which don't have a
360 * ModeratedExtension as being approved (hence they are *not* in the
361 * returned List).
362 *
363 * @return A List of EntityBeans
364 */
365 public static List filterNonApproved(List beans) {
366 if (beans != null) {
367 return ModeratedExtension.filterNonApproved(beans.iterator());
368 } else {
369 return new ArrayList();
370 }
371 }
372
373 /**
374 * Filter and keep non-approved EntityBeans from an Iterator of EntityBean.
375 * Note this considers all the EntityBeans which don't have a
376 * ModeratedExtension as being approved (hence they are *not* in the
377 * returned List).
378 *
379 * @return A List of EntityBeans
380 */
381 public static List filterNonApproved(Iterator beans) {
382 List nonapproved = new ArrayList();
383
384 if (beans != null) {
385 EntityBean bean;
386 while (beans.hasNext()) {
387 bean = (EntityBean) beans.next();
388 if (ModeratedExtension.needApproval(bean)) {
389 // keep this one
390 nonapproved.add(bean);
391 }
392 }
393 }
394
395 return nonapproved;
396 }
397
398 /**
399 * Says whether a given EntityBean requires approval.
400 *
401 * @return A boolean
402 */
403 public static boolean needApproval(EntityBean bean) {
404 ModeratedExtension mod = ModeratedExtension.getFor(bean);
405 return ((mod != null) && (mod.getIsModerated()) && (!mod.getIsApproved()));
406 }
407
408 /**
409 * Says whether a given EntityBean is moderated.
410 *
411 * @return A boolean
412 */
413 public static boolean isModerated(EntityBean bean) {
414 ModeratedExtension mod = ModeratedExtension.getFor(bean);
415 return ((mod != null) && (mod.getIsModerated()));
416 }
417
418 /**
419 * Filter and keep the EntityBeans which are moderated by
420 * the specific User.
421 *
422 * @return A List of EntityBeans
423 */
424 public static List filterModeratedBy(Iterator beans, User user) {
425 List result = new ArrayList();
426
427 if ((beans != null) && (user != null)) {
428 EntityBean bean;
429 User moderator;
430 while (beans.hasNext()) {
431 bean = (EntityBean) beans.next();
432 moderator = ModeratedExtension.getModeratorUser(bean);
433 if ((moderator != null) && (moderator.getId() == user.getId())) {
434 // keep this one
435 result.add(bean);
436 }
437 }
438 }
439
440 return result;
441 }
442
443 /**
444 * Gets who, if anybody, is moderating the bean.
445 * Note that if the bean is marked as not being moderated,
446 * this will return null regardless of the getModeratorUser
447 * property of the bean's ModeratedExtension.
448 *
449 * @return A User, possibly null
450 */
451 public static User getModeratorUser(EntityBean bean) {
452 ModeratedExtension mod = ModeratedExtension.getFor(bean);
453 if ((mod != null) && (mod.getIsModerated())) {
454 return mod.getModeratorUser();
455 }
456
457 return null;
458 }
459
460 /**
461 * Says who, if anybody, is moderating the bean.
462 *
463 * @return A String, possibly EMPTY_STRING
464 */
465 public static String getModeratorName(EntityBean bean) {
466 User moderator = getModeratorUser(bean);
467
468 if (moderator != null) {
469 return moderator.getFirstName()+SPACE+moderator.getLastName();
470 }
471
472 return EMPTY_STRING;
473 }
474
475 private static String EMPTY_STRING = "";
476 private static String SPACE = " ";
477 }
478
479
480