KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > module > gui > html > StateManager


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 package org.mmbase.module.gui.html;
11
12 import java.util.*;
13
14 import org.mmbase.util.*;
15 import org.mmbase.util.logging.*;
16 import org.mmbase.module.core.*;
17 import org.mmbase.module.corebuilders.*;
18 import org.mmbase.module.builders.*;
19
20
21 /**
22  * The StateManager class maintains a list of EditStates for users logged on to MMBase through SCAN.
23  * It provides the states so a user can browse the SCAN editors and edit objects, letting the server remember the change history.
24  * Changes to the state are made either by calling a replace ($MOD) command, or by processing parameters passed to a SCAN page.
25  * State info (such as the current editnode number) can be retrieved using $MOD.
26  *
27  * @application SCAN
28  * @author Daniel Ockeloen
29  * @author Hans Speijer
30  * @author Pierre van Rooden
31  * @version $Id: StateManager.java,v 1.18 2005/11/23 15:45:13 pierre Exp $
32  */

33
34 public class StateManager implements CommandHandlerInterface {
35
36     // Logger
37
private static Logger log = Logging.getLoggerInstance(StateManager.class.getName());
38
39     /**
40      * Reference to the MMBase module.
41      */

42     public MMBase mmBase;
43
44     /**
45      * Username to EditState mappings.
46      * Each user has an editstate, stored in the statemanager.
47      * @scope private
48      */

49     Hashtable editStates; // HashTable with editstates indexed by usernames
50

51     /**
52      * Initialises the StateManager, by creating a new (empty) map of editstates.
53      * @param mmBase reference to the MMBase module
54      */

55     public StateManager(MMBase mmBase) {
56         this.mmBase = mmBase;
57         editStates = new Hashtable();
58     }
59
60     /**
61      * Loads all previously persistified editstates from the database.
62      * @deprecated-now removed per 1.7, does not do anything, and is never called
63      */

64     public void initUserStates() {
65     }
66
67     /**
68      * Retrieves the EditState for a user, or creates a new one if the user did not yet have an EditState assigned.
69      * The EditState contains status information for a specific user (which node is being edited, for instance).
70      * EditStates are associated by username. They are kept in memory as long as teh StateManager is.
71      * @param user the user for which to retrieve an EditState object
72      * @return the EditState objevt associated with this user
73      */

74     public EditState getEditState(String JavaDoc user) {
75         EditState result = (EditState)editStates.get(user);
76         if (result == null) {
77             result = new EditState(user,mmBase);
78             editStates.put(user, result);
79         }
80         return result;
81     }
82
83     /**
84      * Handle a $MOD command.
85      * This generally replaces the command in the SCAN page with the value returned by the command.<br />
86      * Commands include:
87      * <ul>
88      * <li>SETBUILDER-buildername[-joinnode]: Adds a new node of the specified builder type to the user's stack of working objects, and makes it current. If 'joinnode' is specified, the JOINNODE variable is set to this value</li>
89      * <li>GETBUILDER : lists the type of the current working object.</li>
90      * <li>DELBUILDER : drop the current working object. If the stack of working objects is not empty, the top object becomes current.</li>
91      * <li>CLEARBUILDERS : drop all working objects</li>
92      * <li>ADDRELATION : obsolete </li>
93      * <li>SETHTMLVALUE-name-value : sets teh value fo teh variable 'name' to 'value'</li>
94      * <li>GETHTMLVALUE-name : returns the value of the variable 'name' </li>
95      * <li>SETEDITNODE : ??? </li>
96      * <li>GETEDITNODE : ??? </li>
97      * <li>GETEDITSRCDUTCHNAME : ??? </li>
98      * <li>GETEDITDSTDUTCHNAME : ??? </li>
99      * <li>GETEDITSRCNAME : ??? </li>
100      * <li>GETEDITDSTNAME : ??? </li>
101      * <li>GETEDITSRCNODE : ??? </li>
102      * <li>GETEDITDSTNODE : ??? </li>
103      * <li>GETEDITSRCGUIINDICATOR : ??? </li>
104      * <li>GETEDITDSTGUIINDICATOR : ??? </li>
105      * <li>NEWNODE : ??? </li>
106      * <li>NEWINSNODE-sourcenr-destinationnr-role : Creates a relation object node using the specified parameters and makes it current</li>
107      * <li>REMOVENODE : ??? </li>
108      * <li>REMOVEEDITOR : ??? </li>
109      * <li>ISCHANGED : ??? </li>
110      * </ul>
111      */

112     public String JavaDoc replace(scanpage sp, StringTokenizer commands) {
113         // Retrieve the username.
114
// Or at least, that is the intention.
115
// What this method REALLY does is authenticate the user (even if he was authenticated before).
116
// Depending on the system you use this can drastically slow down the editors.
117
String JavaDoc userName=HttpAuth.getRemoteUser(sp);
118         if (userName==null) return "StateManager-> not logged in";
119
120         // obtain an editstate for the user
121
EditState state = getEditState(userName);
122
123         if (commands.hasMoreTokens()) {
124             String JavaDoc token = commands.nextToken();
125             if (token.equals("SETBUILDER")) {
126                 if (commands.hasMoreTokens()) {
127                     state.setBuilder(commands.nextToken());
128                     if (commands.hasMoreTokens()) {
129                         state.setHtmlValue("JOINNODE",commands.nextToken());
130                     } else {
131                         state.setHtmlValue("JOINNODE","");
132                     }
133                 }
134             } else if (token.equals("GETBUILDER")) {
135                     return state.getBuilderName();
136             } else if (token.equals("DELBUILDER")) {
137                     state.popState();
138             } else if (token.equals("CLEARBUILDERS")) {
139                     state.clear();
140             } else if (token.equals("ADDRELATION")) {
141                     log.warn("ADDRELATION is deprecated in "+sp.getUrl()+"; use NEWINSNODE");
142                     state.addRelation(userName);
143             } else if (token.equals("SETHTMLVALUE")) {
144                     state.setHtmlValue(commands.nextToken(),commands.nextToken());
145             } else if (token.equals("GETHTMLVALUE")) {
146                     return state.getHtmlValue(commands.nextToken());
147             } else if (token.equals("SETEDITNODE")) {
148                     state.setEditNode(commands.nextToken(),userName);
149             } else if (token.equals("GETEDITNODE")) {
150                     return ""+state.getEditNodeNumber();
151             } else if (token.equals("GETEDITSRCDUTCHNAME")) {
152                     return state.getEditNodeSrcDutchName();
153             } else if (token.equals("GETEDITDSTDUTCHNAME")) {
154                     return state.getEditNodeDstDutchName();
155             } else if (token.equals("GETEDITSRCNAME")) {
156                     return state.getEditNodeSrcName();
157             } else if (token.equals("GETEDITDSTNAME")) {
158                     return state.getEditNodeDstName();
159             } else if (token.equals("GETEDITSRCNODE")) {
160                     return ""+state.getEditNodeSrcNumber();
161             } else if (token.equals("GETEDITDSTNODE")) {
162                     return ""+state.getEditNodeDstNumber();
163             } else if (token.equals("GETEDITSRCGUIINDICATOR")) {
164                     return state.getEditNodeSrcGuiIndicator();
165             } else if (token.equals("GETEDITDSTGUIINDICATOR")) {
166                     return state.getEditNodeDstGuiIndicator();
167             } else if (token.equals("NEWNODE")) {
168                     state.NewNode(userName);
169             } else if (token.equals("NEWINSNODE")) {
170                     newInsNode(state,userName,commands);
171             } else if (token.equals("REMOVENODE")) {
172                     state.removeNode();
173             } else if (token.equals("REMOVEEDITOR")) {
174                     state.popState();
175             } else if (token.equals("ISCHANGED")) {
176                     if (state.isChanged()) {
177                         return "YES";
178                     } else {
179                         return "NO";
180                     }
181             }
182             return "";
183         }
184
185         return "Command not defined (StateManager)";
186     }
187
188
189     /**
190      * Creates a new Node, depending on the builder name (or relation name) specified in the StringTokenizer.
191      * This method is used to create relation nodes
192      * @param ed Editstate in which to add the new node.
193      * @param userName User who becomes owner of the new node
194      * @param tok Tokens used to configure the node. The next three tokens should be:
195      * <ul>
196      * <li> The number of the node to link FROM </li>
197      * <li> The number of the node to link TO</li>
198      * <li> The name of the builder to use or relation to add (determines type of node and/or relation)</li>
199      * </ul>
200      * @return Always true. If the addition was successful, a new node has been added to the EditState object.
201      */

202     boolean newInsNode(EditState ed,String JavaDoc userName,StringTokenizer tok) {
203         try {
204             String JavaDoc tmp=tok.nextToken();
205             int n1=Integer.parseInt(tmp);
206
207             tmp=tok.nextToken();
208             int n2=Integer.parseInt(tmp);
209
210             String JavaDoc builder=tok.nextToken();
211
212             int rtype=-1;
213
214             // tests if the 'builder' specified is actually a relationname.
215
// If so, the number of the relation in RelDef is obtained,
216
// and the name of the builder to use is determined (if explicitly given)).
217

218             MMObjectBuilder bul = null;
219             rtype = mmBase.getRelDef().getNumberByName(builder);
220
221             if ((rtype!=-1) && (RelDef.usesbuilder)) { // relation found
222
MMObjectNode node=mmBase.getRelDef().getNode(rtype); // retrieve the reldef node
223
bul = mmBase.getRelDef().getBuilder(node);
224             } else {
225                 bul = mmBase.getMMObject(builder);
226             }
227
228             // check whether the builder is a valid relationbuilder.
229
// otherwise assign InsRel
230
// note that is the builder specified is not an InsRel-derived builder, it will be overridden
231

232             if (!(bul instanceof InsRel)) {
233                 bul=mmBase.getInsRel();
234             }
235
236             ed.popState();
237             ed.setBuilder(bul.getTableName());
238
239             ed.NewNode(userName);
240             MMObjectNode node=ed.getEditNode();
241             node.setValue("snumber",n1);
242             node.setValue("dnumber",n2);
243
244             // If rtype is unknown, try to get the type from TypeRel
245

246             if ((bul == mmBase.getInsRel()) && (rtype==-1)) {
247                 rtype=mmBase.getTypeRel().getAllowedRelationType(bul.getNodeType(n1),bul.getNodeType(n2));
248             }
249
250             // assign rtype. Note that rtype is only set if it is actually known.
251
// in rare cases, rtype can be -1. This happens if the relationname specified is the name of a
252
// relationbuilder for which no relation definition with the same name is defined.
253
if (rtype!=-1) {
254                 node.setValue("rnumber",rtype);
255             }
256
257         } catch (Exception JavaDoc e) {
258             log.error("StateManager -> Can't create insnode");
259             e.printStackTrace();
260         }
261         return true;
262     }
263
264
265     /**
266      * setSearchVals
267      * @javadoc
268      */

269     boolean setSearchValues(EditState ed, Hashtable vars) {
270         String JavaDoc varline;
271         ed.clearSearchValues();
272         for (Enumeration h=vars.keys();h.hasMoreElements();) {
273             varline=(String JavaDoc)h.nextElement();
274             StringTokenizer tok = new StringTokenizer(varline,"-\n\r");
275                 String JavaDoc var=tok.nextToken();
276                 if (var.equals("STATE")) var=tok.nextToken();
277                 if (var.equals("SEARCHVALUE")) {
278                     String JavaDoc key=tok.nextToken();
279                     String JavaDoc keyval=(String JavaDoc)vars.get("STATE-SEARCHVALUE-"+key);
280                     ed.setSearchValue(key,keyval);
281                 }
282         }
283         MMObjectBuilder bul=ed.getBuilder();
284         ed.setSelectionQuery(createSelectionQuery(ed.getSearchValues(),bul));
285         return true;
286     }
287
288     /**
289      * @javadoc
290      */

291     String JavaDoc createSelectionQuery(Hashtable skeys,MMObjectBuilder bul) {
292         String JavaDoc where="MMNODE ",key,val;
293         String JavaDoc name=bul.getTableName();
294             for (Enumeration h=skeys.keys();h.hasMoreElements();) {
295                 key=(String JavaDoc)h.nextElement();
296                 val=(String JavaDoc)skeys.get(key);
297                     if (val!=null && !val.equals("")) {
298                     // val to lower for search
299
val=val.toLowerCase();
300                     if (key.equals("maxage")) {
301                         int ival=30;
302                         try {
303                             ival=Integer.parseInt(bul.getSearchAge());
304                         } catch(Exception JavaDoc e) {}
305                         try {
306                             ival=Integer.parseInt(val);
307                         } catch(Exception JavaDoc e) {}
308                         DayMarkers daym=(DayMarkers)bul.getMMBase().getMMObject("daymarks");
309                         int mark=daym.getDayCountAge(ival);
310                         if (where.equals("MMNODE ")) {
311                             where+=name+".number=G"+mark;
312                         } else {
313                             where+="+"+name+".number=G"+mark;
314                         }
315                     } else {
316                         if (where.equals("MMNODE ")) {
317                             where+=name+"."+key+"==*"+val+"*";
318                         } else {
319                             where+="+"+name+"."+key+"==*"+val+"*";
320                         }
321                     }
322                 }
323             }
324
325         return where;
326     }
327
328     /**
329      * An object has been selected and the EditState of the specific user
330      * is updated.
331      * @deprecated-now removed per 1.7, does not do anything, and is never called
332      */

333     void updateSelectedObject(String JavaDoc user, String JavaDoc objectID) {
334     }
335
336     /**
337      * A field has been selected to edit and the EditState for the specific
338      * user is updated.
339      * @deprecated-now removed per 1.7, does not do anything, and is never called
340      */

341     void updateEditField(String JavaDoc user, String JavaDoc fieldName) {
342     }
343
344     /**
345      * a new relation has been initiated and the EditState for the specific
346      * user is updated.
347      * @deprecated-now removed per 1.7, does not do anything, and is never called
348      */

349     void initLink(String JavaDoc user, String JavaDoc objectType) {
350     }
351
352     /**
353      * List commands
354      * @javadoc
355      */

356     public Vector getList(scanpage sp, StringTagger args, StringTokenizer command) throws org.mmbase.module.ParseException {
357         String JavaDoc token;
358         String JavaDoc userName=HttpAuth.getRemoteUser(sp);
359         EditState state = getEditState(userName);
360         Vector result = new Vector();
361
362         if (command.hasMoreTokens()) {
363             token = command.nextToken();
364             if (token.equals("GETOPENBUILDERS")) {
365                 return getOpenBuilders(state,args);
366             }
367         }
368         result.addElement("No List command defined (FieldEditor)");
369         return result;
370     }
371
372     /**
373      * The hook that passes all form related pages to the correct handler
374      * @javadoc
375      */

376     public boolean process(scanpage sp, StringTokenizer command,Hashtable cmds, Hashtable vars) {
377         String JavaDoc token;
378         String JavaDoc userName=HttpAuth.getRemoteUser(sp);
379         EditState state = getEditState(userName);
380
381         String JavaDoc cmd,cmdline;
382         for (Enumeration h=cmds.keys();h.hasMoreElements();) {
383             cmdline=(String JavaDoc)h.nextElement();
384             StringTokenizer tok = new StringTokenizer(cmdline,"-\n\r");
385             if (tok.hasMoreTokens()) {
386                 cmd=tok.nextToken(); // read away dummy STATE-
387
cmd=tok.nextToken();
388                 if (cmd.equals("SETSEARCHVALUES")) return setSearchValues(state,vars);
389                 if (cmd.equals("REMOVENODE")) {
390                     String JavaDoc qw=(String JavaDoc)cmds.get("STATE-REMOVENODE");
391                     if (qw.equals("YES")) {
392                         // delete the relations to this node and
393
// the node itself
394
state.removeRelations();
395                         state.removeNode();
396                         state.setHtmlValue("Chooser","select");
397                         state.setHtmlValue("Work","empty");
398                     }
399                 } else
400                 if (cmd.equals("REMOVERELATION")) {
401                     String JavaDoc qw=(String JavaDoc)cmds.get("STATE-REMOVERELATION");
402                     if (qw.equals("YES")) {
403                         state.removeNode();
404                         state.popState();
405                         state.setHtmlValue("Chooser","realFieldEdit");
406                         state.setHtmlValue("Work","empty");
407                     }
408                 } else
409                 if (cmd.equals("NEXTFIELD")) {
410                     String JavaDoc currentfield=(String JavaDoc)cmds.get("STATE-NEXTFIELD");
411                     state.setHtmlValue("Work","nextfield");
412                     MMObjectBuilder bul=state.getBuilder();
413                     FieldDefs ndefs=bul.getNextField(currentfield);
414                     if (ndefs!=null) {
415                         state.setHtmlValue("NEXTFIELD",""+ndefs.getGUIType()+".shtml?"+ndefs.getDBName()+"+"+ndefs.getGUIName(state.getLanguage()));
416                     } else {
417                         state.setHtmlValue("NEXTFIELD","empty.shtml");
418                     }
419                 } else
420                 if (cmd.equals("SETHTMLVALUE")) {
421                     String JavaDoc field=tok.nextToken();
422                     String JavaDoc value=(String JavaDoc)cmds.get("STATE-SETHTMLVALUE-"+field);
423                     state.setHtmlValue(field,value);
424                 }
425             }
426         }
427         return false;
428     }
429
430     /**
431      * @javadoc
432      */

433     public Vector getOpenBuilders(EditState state,StringTagger args) {
434         Vector results=new Vector();
435         Vector nodes=state.getEditStates();
436         EditStateNode node;
437         MMObjectNode curnode=state.getEditNode(); // problem
438
for (Enumeration h=nodes.elements();h.hasMoreElements();) {
439             node=(EditStateNode)h.nextElement();
440             results.addElement(node.getDutchBuilderName());
441             if (curnode==node.getEditNode()) {
442                 results.addElement("a");
443             } else {
444                 results.addElement("n");
445             }
446         }
447         args.setValue("ITEMS","2");
448         return results;
449     }
450
451     /**
452      * Retrieves the EditState for a user, or creates a new one if the user did not yet have an EditState assigned.
453      * @deprecated-now removed per 1.7, use getEditState() instead.
454      * @param user the user for which to retrieve an EditState object
455      * @return the EditState objevt associated with this user
456      */

457     public EditState getState(String JavaDoc user) {
458         EditState result;
459
460         result = (EditState)editStates.get(user);
461         if (result == null) result = new EditState(user,mmBase);
462
463         return result;
464     }
465
466 }
467
468
Popular Tags