View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2000 William Chesters
6    *
7    * Part of Melati (http://melati.org), a framework for the rapid
8    * development of clean, maintainable web applications.
9    *
10   * Melati is free software; Permission is granted to copy, distribute
11   * and/or modify this software under the terms either:
12   *
13   * a) the GNU General Public License as published by the Free Software
14   *    Foundation; either version 2 of the License, or (at your option)
15   *    any later version,
16   *
17   *    or
18   *
19   * b) any version of the Melati Software License, as published
20   *    at http://melati.org
21   *
22   * You should have received a copy of the GNU General Public License and
23   * the Melati Software License along with this program;
24   * if not, write to the Free Software Foundation, Inc.,
25   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26   * GNU General Public License and visit http://melati.org to obtain the
27   * Melati Software License.
28   *
29   * Feel free to contact the Developers of Melati (http://melati.org),
30   * if you would like to work out a different arrangement than the options
31   * outlined here.  It is our intention to allow Melati to be used by as
32   * wide an audience as possible.
33   *
34   * This program is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37   * GNU General Public License for more details.
38   *
39   * Contact details for copyright holder:
40   *
41   *     William Chesters <williamc At paneris.org>
42   *     http://paneris.org/~williamc
43   *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44   */
45  package org.melati.admin;
46  
47  
48  import java.util.Enumeration;
49  import java.util.Hashtable;
50  
51  import org.melati.Melati;
52  import org.melati.poem.AccessPoemException;
53  import org.melati.poem.Field;
54  import org.melati.poem.Persistent;
55  import org.melati.poem.Table;
56  import org.melati.poem.Treeable;
57  import org.melati.poem.util.ArrayUtils;
58  import org.melati.poem.util.StringUtils;
59  import org.melati.template.MarkupLanguage;
60  import org.melati.util.JSStaticTree;
61  import org.melati.util.Tree;
62  
63  
64  /**
65   * A utility object for placing in a <code>ServletTemplateContext</code>.
66   */
67  public class AdminUtils {
68    
69    private String contextPath;
70    private String servletURL;
71    private String staticURL;
72    private String logicalDatabase;
73    
74    /**
75     *  Constructor. 
76     */
77    public AdminUtils(Melati melati) {
78      this(melati.getRequest() == null ? null : melati.getRequest().getContextPath(),
79           melati.getRequest() == null ? null : melati.getRequest().getServletPath(),
80           melati.getConfig().getStaticURL() ,
81           melati.getPoemContext().getLogicalDatabase());    
82    }
83  
84    /**
85     *  Constructor. 
86     */
87    private AdminUtils(String contextPath, String servlet, 
88                      String staticURL, String logicalDatabase) {
89      this.contextPath = contextPath;
90      this.servletURL = contextPath + servlet;
91      this.staticURL = staticURL;
92      this.logicalDatabase = logicalDatabase;
93      // HACK if we are using 2.0 Servlet API then zone is
94      // included in servlet and contextPath is empty
95      if (contextPath == "") {
96        this.contextPath = servlet.substring(0, servlet.lastIndexOf("/"));
97      }
98    }
99    
100   /**
101    * @return the name of the default table to display  
102    */
103   public static String getPrimaryDisplayTable(Melati melati) { 
104     if (Admin.getPrimaryDisplayTable() == null) 
105       Admin.setPrimaryDisplayTable(melati.getDatabase().
106           getSettingTable().get(Admin.class.getName() + ".PrimaryDisplayTable"));
107     if (Admin.getPrimaryDisplayTable() == null)
108       Admin.setPrimaryDisplayTable("columninfo");
109     return Admin.getPrimaryDisplayTable();
110   }
111   
112   /**
113    * @param melati to get db from
114    * @return the stylesheet for screen media  
115    */
116   public String getScreenStylesheetURL(Melati melati) {
117     if (Admin.getScreenStylesheetURL() == null) 
118       Admin.setScreenStylesheetURL(melati.getDatabase().
119           getSettingTable().get(Admin.class.getName() + ".ScreenStylesheetURL"));
120     if (Admin.getScreenStylesheetURL() == null)
121       Admin.setScreenStylesheetURL("/admin.css");
122     return staticURL + Admin.getScreenStylesheetURL();
123   }
124   /**
125    * @return the settings table setup url
126    */
127   public String getSetupURL() {
128     return servletURL + "/" + logicalDatabase + 
129         "/setting/setup";
130   }
131   /**
132    * @return the summary url
133    */
134   public String getSummaryURL() {
135     return servletURL + "/" + logicalDatabase + 
136         "/Summary";
137   }
138   
139   
140   /**
141    * Check if setting in db, provide default if not, do not 
142    * write default to db. 
143    * 
144    * @param melati to get db from
145    * @return the homepage URL for this databse  
146    */
147   public String getHomepageURL(Melati melati) {
148     if (Admin.getHomepageURL() == null) 
149       Admin.setHomepageURL(melati.getDatabase().
150           getSettingTable().get(Admin.class.getName() + ".HomepageURL"));
151     if (Admin.getHomepageURL() == null)
152       Admin.setHomepageURL("http://www.melati.org/");
153     return Admin.getHomepageURL();
154   }
155   
156   /**
157    * @param melati the melati
158    * @param name of template
159    * @return name prepended with ldb, table and troid if not null
160    */
161   public String getURL(Melati melati, String name) { 
162     String url = servletURL + "/" + logicalDatabase;
163     if (melati.getTable() != null)
164       url += "/" + melati.getTable().getName();
165     if (melati.getObject() != null)
166       url += "/" + melati.getObject().getTroid();
167     return url + "/" + name;
168   }
169   /**
170    * @return name prepended with ldb and table name
171    */
172   public String getURL(Table<?> table, String name) { 
173     String url = servletURL + "/" + logicalDatabase;
174     url += "/" + table.getName();
175     return url + "/" + name;
176   }
177   
178   
179   /** @return The Main URL. */
180   public String getMainURL(String ld) {
181     String url = servletURL + "/" + ld;
182     return url + "/Main";
183   }
184   /** @return The Main URL. */
185   public String getMainURL(Melati melati) {
186     return getURL(melati, "Main");
187   }
188   
189   /** @return The Top URL. */
190   public String getTopURL(Melati melati) {
191     return getURL(melati, "Top");
192   }
193   
194   /**
195    * @return The Bottom URL.
196    */
197   /*
198    * Do not think this is used
199   public String getBottomURL(Table<?> table, Melati melati) {
200     return  servletURL + "/" + logicalDatabase + 
201         "/" + table.getName() +
202         (melati.getObject() != null &&  
203                 melati.getObject().getTable() == table ? 
204                         "/" + melati.getObject().getTroid() 
205                         : "") + 
206         "/Bottom";
207   }
208   */
209   /**
210    * @return The Bottom URL.
211    */
212   public String getBottomURL(Melati melati) {
213     String url =  servletURL + "/" + logicalDatabase + "/";
214     if (melati.getTable() != null)
215       url += melati.getTable().getName();
216     else 
217       url += getPrimaryDisplayTable(melati); 
218     if (melati.getObject() != null)
219       url += "/" + melati.getObject().getTroid();
220     url += "/Bottom";
221     return url;
222   }
223   
224   /**
225    * @return The Left URL.
226    */
227   public String getTableURL(Table<?> table) {
228     return getURL(table, "Table");
229   }
230   
231   /**
232    * @return The Right URL.
233    */
234   public String getRecordURL(Persistent object) throws AccessPoemException {
235     return servletURL + "/" + logicalDatabase + "/" + object.getTable().getName()
236             + "/" + object.troid() + "/Record";
237   }
238 
239   /**
240    * @return The Right URL.
241    */
242   public String getRecordURL(Persistent object, String returnTarget, String returnURL) throws AccessPoemException {
243     return servletURL + "/" + logicalDatabase + "/" + object.getTable().getName()
244             + "/" + object.troid() + "/Record" + 
245             "?returnTarget=" + returnTarget + 
246             "&returnURL=" + returnURL;
247   }
248 
249   /**
250    * @return The Right URL.
251    */
252   public String getRecordURL(Melati melati) throws AccessPoemException {
253     return getURL(melati, "Record");
254   }
255 
256   /**
257    * @return The Primary Select URL.
258    */
259   public String getPrimarySelectURL(Melati melati) {
260     return getURL(melati, "PrimarySelect");
261   }
262 
263   /**
264    * @return The Selection URL.
265    */
266   public String getSelectionURL(Table<?> table) {
267     return getSelectionURL(table,"admin_record");
268   }
269   /**
270    * @return The Selection URL.
271    */
272   public String getSelectionURL(Table<?> table, String returnTarget) {
273     return getSelectionURL(table, "admin_record", returnTarget);
274   }
275   /**
276    * @param table
277    * @param targetPane
278    * @param returnTarget
279    * @return the url
280    */
281   public String getSelectionURL(Table<?> table, String targetPane, String returnTarget) {
282     return servletURL + "/" + logicalDatabase + "/" + table.getName()
283             + "/Selection?" +
284             "target=" + targetPane +  
285             "&returnTarget=" + returnTarget;
286   }
287   
288   /**
289    * Toggle the sort order of column.
290    * @return the same url with the toggle field added or removed
291    */
292   public String getToggledOrderSelectionURL(Melati melati, String field, String value) { 
293     String url = melati.sameURLWith(field,value);
294     String toggleField = "&" + field + "-toggle=true";
295     if (url.endsWith(toggleField))
296       return url.substring(0,url.length() - toggleField.length());
297     else 
298       return url + "&" + field + "-toggle=true";
299   }
300   
301   /**
302    * @param melati
303    * @return The Selection URL.
304    */
305   public String getSelectionURL(Melati melati) {
306     return getSelectionURL(melati,"admin_record");    
307   }
308 
309   /**
310    * @return The Selection URL.
311    */
312   public String getSelectionURL(Melati melati, String returnTarget) {
313     return servletURL + "/" + 
314         logicalDatabase + "/" + 
315         melati.getTable().getName()
316           + "/Selection?" +
317           "target=admin_record" + 
318           "&returnTarget=" + (returnTarget == null ? "" : returnTarget) + 
319           (melati.getObject() == null ? 
320               "" : 
321               "&field_id=" + melati.getObject().troid());
322   }
323   
324   /**
325    * @return The Selection Right URL.
326    */
327   public String getSelectionRightURL(Table<?> table) {
328     return servletURL + "/" + logicalDatabase + "/" + table.getName()
329     + "/SelectionRight";
330   }
331 
332   /**
333    * @return The Navigation URL.
334    */
335   public String getNavigationURL(Table<?> table) {
336     return servletURL + "/" + logicalDatabase + "/" + table.getName()
337     + "/Navigation";
338   }
339   
340   /**
341    * @return The Edit Header URL.
342    */
343   public String getEditHeaderURL(Melati melati) throws AccessPoemException {
344     if (melati.getObject() == null)
345       return getURL(melati, "blank");
346     else
347       return getURL(melati, "EditHeader");
348   }
349 
350   /**
351    * @return The Edit URL.
352    */
353   public String getEditURL(Melati melati) throws AccessPoemException {
354     if (melati.getObject() == null)
355       return getURL(melati, "blank");
356     else
357       return getURL(melati, "Edit");
358   }
359   /**
360    * @return The Edit URL.
361    */
362   public String getEditURL(Persistent object) throws AccessPoemException {
363     return servletURL + "/" + logicalDatabase + "/" + object.getTable().getName()
364             + "/" + object.troid() + "/Edit";
365   }
366 
367   /**
368    * @param melati
369    * @return the name of the Record Fields frame
370    */
371   public String getEditFrameName(Melati melati) { 
372     String name = "admin_edit";
373     name += "_" + melati.getTable().getName();
374     if (melati.getObject() != null) 
375       name += "_" + melati.getObject().troid();
376     return name;
377   }
378   /**
379    * @return The Tree URL.
380    */
381   public String getTreeURL(Persistent object) throws AccessPoemException {
382     return servletURL + "/" + logicalDatabase + "/" + object.getTable().getName()
383             + "/" + object.troid() + "/Tree";
384   }
385   
386   /**
387    * @return The Tree URL.
388    */
389   public String getTreeURL(Table<?> table) throws AccessPoemException {
390     return servletURL + "/" + logicalDatabase + "/" + table.getName()
391             +  "/Tree";
392   }
393   
394 
395   /**
396    * @return The Add URL.
397    */
398   public String getAddURL(Table<?> table) throws AccessPoemException {
399     return servletURL
400             + "/"
401             + logicalDatabase
402             + "/" 
403             + table.getName() 
404             + "/" 
405             + "Add";
406   }
407 
408   /**
409    * @return The Popup URL.
410    */
411   public String getPopUpURL(Table<?> table) {
412     return servletURL + "/" + logicalDatabase + "/" + table.getName() + "/PopUp";
413   }
414   
415   /**
416    * @return The Selection Window URL.
417    */
418   public String getSelectionWindowURL(Table<?> table) {
419     return servletURL + "/" + logicalDatabase + "/" + table.getName()
420             + "/SelectionWindow?target=";
421   }
422 
423   /**
424    * @return The Selection Window Primary Select URL.
425    */
426   public String getSelectionWindowPrimarySelectURL(Table<?> table) {
427     return servletURL + "/" + logicalDatabase + "/" + table.getName()
428             + "/SelectionWindowPrimarySelect";
429   }
430 
431   /**
432    * @return The Selection Window Selection URL.
433    */
434   public String getSelectionWindowSelectionURL(Table<?> table) {
435     return servletURL + "/" + logicalDatabase + "/" + table.getName()
436             + "/SelectionWindowSelection";
437   }
438   
439   /**
440    * @return The Status URL.
441    */
442   public String getStatusURL() {
443     return contextPath + "/org.melati.admin.Status/" + logicalDatabase;
444   }
445   
446   /**
447    * @return The Session Analysis URL.
448    */
449   public String getSessionURL() {
450     return contextPath + "/org.melati.test.SessionAnalysisServlet";
451   }
452   
453   /**
454    * @return The URL for DSD generation. 
455    */
456   public String getDsdURL() {
457     return servletURL + "/" + logicalDatabase + "/DSD";
458   }
459   
460   /**
461    * In an insert situation we will not have a Troid, so cannot pass it through.
462    * If your upload handler depends on having a persistent, then you should
463    * override your upload template so that it prevents uploading in an insert
464    * situation.
465    * 
466    * @param table table object belongs to
467    * @param object the Persistent we are dealing with
468    * @param field the upload field
469    * @return Upload Url
470    */
471   public String getUploadURL(Table<?> table, Persistent object, Field<?> field) {
472     return upload(table, object) + "/Upload?field=" + field.getName();
473   }
474   
475   /**
476    * Upload URL.
477    * 
478    * @param table table object belongs to
479    * @param object the Persistent we are dealing with
480    * @param field the upload field
481    * @return Upload done URL
482    */
483   public String getUploadHandlerURL(Table<?> table, Persistent object, String field) {
484     return upload(table, object) + "/UploadDone?field=" + field;
485   }
486   private String upload(Table<?> table, Persistent object) {
487     String url = servletURL + "/" + logicalDatabase + "/" + table.getName();
488     if (object != null)
489       url += "/" + object.troid();
490     return url;
491   }
492   
493  
494   /**
495    * Render the specials directly to the output.
496    *  
497    * @param melati the Melati
498    * @param ml The MarkupLanguage we are using
499    * @param object a Persistent to render the specials of 
500    * @return an empty String
501    * @throws Exception maybe
502    */
503   public String specialFacilities(Melati melati, MarkupLanguage ml,
504           Persistent object) throws Exception {
505   if (object instanceof AdminSpecialised)
506     melati.getTemplateEngine().expandTemplate(melati.getWriter(),
507           ((AdminSpecialised) object).adminSpecialFacilities(melati, ml),
508           melati.getTemplateContext());
509   return "";
510   /*
511   if (object instanceof AdminSpecialised)
512       return melati.getTemplateEngine().expandedTemplate(
513           melati.getTemplateEngine().template(
514               ((AdminSpecialised) object).adminSpecialFacilities(melati, ml)),
515               melati.getTemplateContext());
516     else 
517       return "";
518     */
519   }
520 
521   /**
522    * @return Defaults to /MelatiStatic/admin
523    */
524   public String getStaticURL() {
525     return staticURL;
526   }
527 
528   /**
529    *  Create a tree. 
530    * @param node  a tree node
531    * @return a tree with node as its root
532    */
533   public JSStaticTree createTree(Treeable node) {
534     return new JSStaticTree(new Tree(node), getStaticURL());
535   }
536   
537   /**
538    *  Create a forest of trees. 
539    * @param table  the table to tree 
540    * @return a tree with node as its root
541    */
542   @SuppressWarnings({ "unchecked", "rawtypes" })
543   public JSStaticTree createForest(Table<?> table) {
544     Object[] all = ArrayUtils.arrayOf((Enumeration) table.selection());
545     Hashtable<Treeable, Boolean> hasParent = new Hashtable<Treeable, Boolean>();
546     for (int i = 0; i < all.length; i++) {
547       if (hasParent.get(all[i]) == null) { 
548         Treeable[] kids = ((Treeable)all[i]).getChildren();
549         for (int j = 0; j < kids.length; j++)
550           hasParent.put(kids[j], Boolean.TRUE);
551       }
552     }
553     int count = 0;
554     for (int i = 0; i < all.length; i++) {
555       if (hasParent.get(all[i]) == null){ 
556         count++;
557       }
558     }
559     Treeable[] roots = new Treeable[count];
560     int j = 0;
561     for (int i = 0; i < all.length; i++) {
562       if (hasParent.get(all[i]) == null) {
563         roots[j] = (Treeable)all[i];
564         j++;
565       }
566     }
567     return new JSStaticTree(roots, getStaticURL());
568   }
569 
570   /**
571    * @param qualifiedName
572    * @return text following the last dot
573    */
574   public static String simpleName(String qualifiedName) { 
575     return qualifiedName.substring(
576         qualifiedName.lastIndexOf('.') != -1 ?
577             qualifiedName.lastIndexOf('.') + 1 : 
578             0,
579         qualifiedName.length());
580   }
581   
582   /**
583    * @param in the String to escape
584    * @return the escaped String
585    */
586   public static String csvEscaped(String in) { 
587     StringBuffer b = new StringBuffer();
588     StringUtils.appendEscaped(b, in, '"', '"');
589     return b.toString();
590   }
591 }