KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > applications > community > modules > CommunityPrc


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10
11 package org.mmbase.applications.community.modules;
12
13 import java.util.*;
14
15 import org.mmbase.util.*;
16 import org.mmbase.module.*;
17 import org.mmbase.module.core.*;
18 import org.mmbase.module.corebuilders.*;
19 import org.mmbase.applications.community.builders.*;
20 import org.mmbase.util.logging.*;
21
22 /**
23  * This module is the general manager for the community objects (chat and forums).
24  * It processes message posts, retrieves info, and generates lists of messages and users.
25  * In this manner, it is more an application than a module.
26  * The community 'application' consists of the Community, Channel, and Message builder.
27  * <br />
28  * The {@link org.mmbase.applications.community.builders.Community} builder is a pool of channels
29  * of a similar type (chatbox, forum, or guestbook).
30  * <br />
31  * The {@link org.mmbase.applications.community.builders.Channel} builder defines a channel - a
32  * 'location' which manages a forum discussion or chat.
33  * <br />
34  * The {@link org.mmbase.applications.community.builders.Message} builder defines a single message - a
35  * persistent message in case of a forum or guestbook, a temporary message in the
36  * case of a chat.
37  * <br />
38  * Optional builders that provide additional information are a Moods builder
39  * (associated with a channel, it may provide backgrounds, colors, or other
40  * dressing), a Chatter builder (which hold the users of a chat or forum), or a
41  * Maps builder (used for generating links).
42  *
43  * @author Dirk-Jan Hoekstra
44  * @author Pierre van Rooden
45  * @version $Id: CommunityPrc.java,v 1.22 2006/08/30 18:05:58 michiel Exp $
46  */

47
48 public class CommunityPrc extends ProcessorModule {
49
50     private static final Logger log = Logging.getLoggerInstance(CommunityPrc.class);
51
52     private Message messageBuilder;
53     private Channel channelBuilder;
54     private Community communityBuilder;
55
56     private VirtualBuilder treeBuilder;
57
58     private MMBase mmb;
59
60     private boolean active = false;
61
62     /**
63      * Create a Community module instance.
64      */

65     public CommunityPrc() {
66     }
67
68     /**
69      * Initialize the community.
70      * Makes sure MMBase starts first (as it needs a reference to its builders).
71      */

72     public void init() {
73         // load MMBase and make sure it is started first
74
mmb = MMBase.getMMBase();
75         activate();
76     }
77
78     /**
79      * Initialize the community and activate it if all builders are present.
80      * @since MMBase-1.7
81      */

82     protected boolean activate() {
83         if (!active) {
84
85             messageBuilder = (Message) mmb.getBuilder("message");
86             if (messageBuilder == null) {
87                 log.info("Community module could not be activated because message builder missing");
88                 return false;
89             }
90             if (!messageBuilder.activate()) {
91                 log.info("Community module could not (yet) be activated because message builder could not be activated" + (messageBuilder == null ? "." : " (" + messageBuilder + ")."));
92                 return false;
93             }
94             communityBuilder = (Community)mmb.getBuilder("community");
95             if (communityBuilder == null) {
96                 log.info("Community builder missing. Communityprc can work without it though.");
97             } else {
98                 if(!communityBuilder.activate()) {
99                     log.info("Community builder could not be activated. Communityprc can work without that though.");
100                 }
101             }
102             channelBuilder = (Channel) mmb.getBuilder("channel");
103             if (channelBuilder == null) {
104                 log.info("Channel builder missing. Communityprc can work without it though.");
105             } else {
106                 if (! channelBuilder.activate()) {
107                     log.info("Channel builder could not be activated. Communityprc can work without that though.");
108                 }
109             }
110             initializeTreeBuilder();
111             active = true;
112             log.service("Community module was activated sucessfully");
113         }
114         return active;
115     }
116
117     /**
118      * Creates a virtual builder for adding functionality to the nodes
119      * of the LIST TREE command.
120      * The returned buuilder is a virtual wrapper around the messagebuilder.
121      * It includes a number of additional, virtual, fields.
122      * These fields are currently not configurable.
123      */

124     private void initializeTreeBuilder() {
125         treeBuilder = new VirtualReferrerBuilder(messageBuilder);
126         treeBuilder.addField(new FieldDefs("list head","string", -1,-1,"listhead",FieldDefs.TYPE_STRING));
127         treeBuilder.addField(new FieldDefs("list tail","string", -1,-1,"listtail",FieldDefs.TYPE_STRING));
128         treeBuilder.addField(new FieldDefs("depth","integer", -1,-1,"depth",FieldDefs.TYPE_INTEGER));
129         treeBuilder.addField(new FieldDefs("nr of replies","integer", -1,-1,"replycount",FieldDefs.TYPE_INTEGER));
130     };
131
132     /**
133      * Handle a $MOD command.
134      * The actual commands are directed to the Message, Channel, and
135      * Community builders.
136      * @param sp The PageInfo (containing http and user info) that calls the function
137      * @param cmds the command to execute
138      * @return the result value as a <code>String</code>
139      */

140     public String JavaDoc replace(PageInfo sp, String JavaDoc cmds) {
141         if (activate()) {
142             StringTokenizer tok = new StringTokenizer(cmds,"-\n\r");
143             if (tok.hasMoreTokens()) {
144                 String JavaDoc cmd = tok.nextToken();
145                 if (cmd.equals("MESSAGE")) {
146                     return messageBuilder.replace(sp, tok);
147                 }
148                 if (cmd.equals("CHANNEL")) {
149                     return channelBuilder.replace(sp, tok);
150                 }
151                 if (cmd.equals("COMMUNITY")) {
152                     return communityBuilder.replace(sp, tok);
153                 }
154             }
155         }
156         return "";
157     }
158
159     /**
160      * Execute the commands provided in the form values.
161      * This method returns values which allow the page to
162      * check whether the operation was succesful (MESSAGE-NUMBER or MESSAGE-ERROR).
163      * The data is stored (added) in the <code>vars<vars> parameter. This allows a system that uses the MMCI
164      * (such as jsp) to retrieve the value.
165      * <br />
166      * XXX: This is a bit of a sloppy way to pass results, and the actual
167      * mechanics may get changed (formalized) in the future.
168      *
169      * @param sp The PageInfo (containing http and user info) that calls the function
170      * @param cmds the commands to process
171      * @param vars variables that were set to be used during processing.
172      * @return the result value as a <code>String</code>
173      */

174     public boolean process(PageInfo sp, Hashtable cmds, Hashtable vars) {
175         boolean result = false;
176         if (activate()) {
177             String JavaDoc token;
178             for (Enumeration h = cmds.keys(); h.hasMoreElements();) {
179                 String JavaDoc key = (String JavaDoc)h.nextElement();
180                 StringTokenizer tok = new StringTokenizer(key , "-\n\r");
181
182                 token = tok.nextToken();
183                 if (token.equals("MESSAGE")) {
184                     if (tok.hasMoreElements()) {
185                         token = tok.nextToken();
186                         /* $MOD-MESSAGE-POST- */
187                         if (token.equals("POST")) {
188                             doPostProcess(sp, cmds, vars);
189                         } else if (token.equals("UPDATE")) {
190                             doUpdateProcess(sp, cmds,vars);
191                         }
192                     }
193                 }
194                 result = true;
195             }
196         }
197         return result;
198     }
199
200     /**
201      * Stores an output parameter as a value.
202      * However, the MMCI does not 'know' sessionInfo, so in those instances
203      * variables are stored in the vars parameter (which is passed back to the
204      * MMCI).
205      * If neither object is supported, no data is returned.
206      */

207     private void setReturnValue(PageInfo sp, Hashtable vars, String JavaDoc name, String JavaDoc value) {
208         if (vars!=null) {
209             // return it in the vars hashtable
210
if (value==null) {
211                 vars.remove(name);
212             } else {
213                 vars.put(name,value);
214             }
215         }
216     }
217
218     /**
219      * Translates the commands for posting a message provided in the form values
220      * to a post() call in the message builder.
221      * @param cmds the commands to process
222      * @param vars variables that were set to be used during processing.
223      * @return <code>true</code> if the post was successful
224      */

225     private boolean doPostProcess(PageInfo sp, Hashtable cmds, Hashtable vars) {
226         // Get the MessageThread, Subject and Body from the formvalues.
227
String JavaDoc tmp = (String JavaDoc)cmds.get("MESSAGE-POST");
228         setReturnValue(sp,vars,"MESSAGE-ERROR",null);
229         try {
230             int messagethreadnr = Integer.parseInt(tmp);
231             String JavaDoc subject = (String JavaDoc)vars.get("MESSAGE-SUBJECT");
232             String JavaDoc body = (String JavaDoc)vars.get("MESSAGE-BODY");
233             tmp = (String JavaDoc)vars.get("MESSAGE-CHANNEL");
234             int channel = Integer.parseInt(tmp);
235
236             // Get user and chatterName
237
tmp = (String JavaDoc)vars.get("MESSAGE-CHATTER");
238             int user;
239             if (tmp != null) user = Integer.parseInt(tmp); else user = -1;
240             String JavaDoc chatterName = (String JavaDoc)vars.get("MESSAGE-CHATTERNAME");
241
242             // Let the messagebuilder post the message.
243
int result=Message.POST_ERROR_UNKNOWN;
244             if (subject != null) {
245                 result=messageBuilder.post(subject, body, channel, messagethreadnr, user, chatterName);
246                 setReturnValue(sp,vars,"MESSAGE-NUMBER",""+result);
247             } else {
248                 result=messageBuilder.post(body, messagethreadnr, user, chatterName);
249                 setReturnValue(sp,vars,"MESSAGE-NUMBER","-1");
250             }
251             if (result<Message.POST_OK) {
252                 String JavaDoc err=messageBuilder.getMessageError(result);
253                 log.error(result+":"+err);
254                 setReturnValue(sp,vars,"MESSAGE-ERROR",err);
255             }
256             return result>=Message.POST_OK;
257         } catch (NumberFormatException JavaDoc e) { // catches erros when parsing integers
258
setReturnValue(sp,vars,"MESSAGE-ERROR",
259                            "Invalid parameter value ( '"+tmp+"' is not a number)");
260             return false;
261         }
262     }
263
264     /**
265      * Translates the commands for updating a message provided in the form values
266      * to a update() call in the message builder.
267      * @param cmds the commands to process
268      * @param vars variables that were set to be used during processing.
269      * @return <code>true</code> if the update was sucecsful
270      */

271     private boolean doUpdateProcess(PageInfo sp, Hashtable cmds, Hashtable vars) {
272         String JavaDoc tmp = (String JavaDoc)cmds.get("MESSAGE-UPDATE");
273         try {
274             // Get the Subject, Body, number from the formvalues.
275
int number = Integer.parseInt(tmp);
276             String JavaDoc subject = (String JavaDoc)vars.get("MESSAGE-SUBJECT");
277             String JavaDoc body = (String JavaDoc)vars.get("MESSAGE-BODY");
278             // Get user and chatterName
279
tmp = (String JavaDoc)vars.get("MESSAGE-CHATTER");
280             int user;
281             if (tmp != null) user = Integer.parseInt(tmp); else user = -1;
282             String JavaDoc chatterName = (String JavaDoc)vars.get("MESSAGE-CHATTERNAME");
283             log.info("MESSAGE-CHATTERNAME="+chatterName);
284             int result=messageBuilder.update(chatterName, user, subject, body, number);
285             if (result<Message.POST_OK) {
286                 String JavaDoc err=messageBuilder.getMessageError(result);
287                 log.error(result+":"+err);
288                 setReturnValue(sp,vars,"MESSAGE-ERROR",err);
289             } else {
290                 setReturnValue(sp,vars,"MESSAGE-NUMBER",""+number);
291             }
292             return result==Message.POST_OK;
293         } catch (NumberFormatException JavaDoc e) { // catches erros when parsing integers
294
setReturnValue(sp,vars,"MESSAGE-ERROR",
295                            "Invalid parameter value ( '"+tmp+"' is not a number)");
296             return false;
297         }
298     }
299
300     /**
301      * Returns a virtual builder used to create node lists from the results
302      * returned by getList().
303      * The default method does not associate the builder with a cloud (mmbase module),
304      * so processormodules that need this association need to override this method.
305      * Note that different lists may return different builders.
306      * @param command the LIST command for which to retrieve the builder
307      * @param params contains the attributes for the list
308      */

309     public MMObjectBuilder getListBuilder(String JavaDoc command, Map params) {
310         activate();
311         if (command.equals("TREE")) return treeBuilder;
312         if (command.equals("WHO") || command.equals("TEMPORARYRELATIONS")) {
313             String JavaDoc type = (String JavaDoc)params.get("TYPE");
314             if (type != null) {
315                 return mmb.getBuilder(type);
316             }
317         }
318         return new VirtualBuilder(mmb);
319     }
320
321     /**
322      * Generates a list of values from a command to the processor.
323      * Recognized commands are TREE, WHO, and TEMPORARYRELATIONS.
324      * @param context the context of the page or calling application (currently, this should be a PageInfo object)
325      * @param command the list command to execute.
326      * @param params contains the attributes for the list
327      * @return a <code>Vector</code> that contains the list values as MMObjectNodes
328      */

329     public Vector getNodeList(Object JavaDoc context, String JavaDoc command, Map params) {
330         activate();
331         if (command.equals("WHO")) return channelBuilder.getNodeListUsers(params);
332         if (command.equals("TEMPORARYRELATIONS")) return getNodeListTemporaryRelations(params);
333         return super.getNodeList(context,command, params);
334     }
335
336     /**
337      * Generates a list of values from a command to the processor.
338      * Recognized commands are TREE, WHO, and TEMPORARYRELATIONS.
339      * If the command is not one of these, it returns null;
340      * @param sp the page context
341      * @param params contains the attributes for the list
342      * @param command the list command to execute.
343      * @return a <code>Vector</code> that contains the list values
344      */

345     public Vector getList(PageInfo sp, StringTagger params, String JavaDoc command) {
346         if (activate()) {
347             if (command.equals("TREE")) return messageBuilder.getListMessages(params);
348             if (command.equals("WHO")) return channelBuilder.getListUsers(params);
349             if (command.equals("TEMPORARYRELATIONS")) return getListTemporaryRelations(params);
350             throw new UnsupportedOperationException JavaDoc("Unknown command '" + command + "'");
351         } else {
352             throw new RuntimeException JavaDoc("CommunityPrc module could not be activated");
353             // return null; // returning null gives NPE in ProcessorModule, how nice it that?
354
}
355     }
356
357     /**
358      * This function returns a vector, like LIST RELATED does, with the values
359      * of the specified fields of the related nodes to a specified node.
360      * Only the field values of nodes that are related via a temporary
361      * <code>insrel</code> object are returned.
362      * Both real and temporary nodes are returned.
363      * <ul>
364      * <li>&lt;LIST TEMPORARYRELATED NODE=&quot;...&quot; TYPE=&quot;...&quot; FIELDS=&quot;...&quot;&gt;</li>
365      * <li>NODE - The node to get the related nodes from.</li>
366      * <li>TYPE - The wanted type of nodes to return.</li>
367      * <li>FIELDS - The values of the fields to return.</li>
368      * </ul>
369      */

370     public Vector getListTemporaryRelations(StringTagger params) {
371         Enumeration relatedNodes = getNodeListTemporaryRelations(params).elements();
372         MMObjectNode relatedNode;
373         Object JavaDoc value;
374         Vector result=new Vector();
375         Vector fields = params.Values("FIELDS");
376         while (relatedNodes.hasMoreElements()) {
377             relatedNode = (MMObjectNode)relatedNodes.nextElement();
378             for (int i = 0; i < fields.size(); i++) {
379                 value = relatedNode.getValue((String JavaDoc)fields.elementAt(i));
380                 if (value != null) result.add("" + value); else result.add("");
381             }
382         }
383         return result;
384     }
385
386     /**
387      * This function returns a vector, like LIST RELATED does, with the values
388      * of the specified fields of the related nodes to a specified node.
389      * Only the field values of nodes that are related via a temporary
390      * <code>insrel</code> object are returned.
391      * Both real and temporary nodes are returned.
392      * <ul>
393      * <li>&lt;LIST TEMPORARYRELATED NODE=&quot;...&quot; TYPE=&quot;...&quot; FIELDS=&quot;...&quot;&gt;</li>
394      * <li>NODE - The node to get the related nodes from.</li>
395      * <li>TYPE - The wanted type of nodes to return.</li>
396      * <li>FIELDS - The values of the fields to return.</li>
397      * </ul>
398      */

399     public Vector getNodeListTemporaryRelations(Map params) {
400         activate();
401         String JavaDoc number = (String JavaDoc)params.get("NODE");
402         MMObjectNode node;
403         if (number == null) {
404             log.warn("getListTemporaryRelations(): Can't find node: " + number);
405             return new Vector();
406         }
407         int offset=0;
408         String JavaDoc tmp = (String JavaDoc)params.get("FROMCOUNT");
409         if (tmp!=null) offset=Integer.parseInt(tmp);
410         int max=Integer.MAX_VALUE;
411         tmp = (String JavaDoc)params.get("MAXCOUNT");
412         if (tmp!=null) max=Integer.parseInt(tmp);
413
414         // reaaaaaallly ugly!
415
if (number.indexOf("_") < 0)
416             node = messageBuilder.getNode(number);
417         else
418             node = (MMObjectNode)MMObjectBuilder.temporaryNodes.get(number);
419         Vector relatedNodes = messageBuilder.getTemporaryRelated(node, (String JavaDoc)params.get("TYPE"),offset,max);
420         return relatedNodes;
421     }
422 }
423
Popular Tags