KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > gui > web > Table


1 /*
2   Copyright (C) 2002-2003 Laurent Martelli <laurent@aopsys.com>
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

17
18 package org.objectweb.jac.aspects.gui.web;
19
20 import java.io.IOException JavaDoc;
21 import java.io.PrintWriter JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Vector JavaDoc;
29 import org.apache.log4j.Logger;
30 import org.objectweb.jac.aspects.gui.*;
31 import org.objectweb.jac.core.Naming;
32 import org.objectweb.jac.core.rtti.ClassItem;
33 import org.objectweb.jac.core.rtti.CollectionItem;
34 import org.objectweb.jac.core.rtti.FieldItem;
35 import org.objectweb.jac.core.rtti.MemberItem;
36 import org.objectweb.jac.core.rtti.MethodItem;
37 import org.objectweb.jac.util.ExtArrays;
38
39 public class Table extends AbstractCollection
40     implements HTMLViewer, TableListener
41 {
42     static Logger logger = Logger.getLogger("gui.table");
43     static Logger loggerEvents = Logger.getLogger("gui.events");
44
45     HTMLViewer[] cellViewers;
46     ExtendedTableModel tableModel;
47
48     public Table(ViewFactory factory, DisplayContext context,
49                  CollectionItem collection, Object JavaDoc substance,
50                  ExtendedTableModel model,
51                  org.objectweb.jac.aspects.gui.CollectionItemView itemView) {
52         super(factory,context,collection,substance,model,itemView);
53         this.tableModel = model;
54         this.multiLineCollection = itemView.getMultiLineCollection();
55         this.groupBy = itemView.getGroupBy();
56         if (model!=null) {
57             this.cellViewers = new HTMLViewer[tableModel.getHeaders().length];
58             setCellRenderers();
59         }
60     }
61
62     CollectionItem multiLineCollection;
63     FieldItem groupBy;
64
65     public void setColumnsInfo(String JavaDoc[] headers, FieldItem[] fields,
66                                ClassItem[] classes, ClassItem[] viewerClasses) {
67         if (!(headers.length==classes.length &&
68               classes.length==viewerClasses.length &&
69               viewerClasses.length==fields.length)) {
70             throw new RuntimeException JavaDoc("headers, fields, classes and "+
71                                        "viewerClasses must be the same size");
72         }
73         this.cellViewers = new HTMLViewer[headers.length];
74     }
75
76     protected void setCellRenderers() {
77         MemberItem[] members = tableModel.getMembers();
78         String JavaDoc[] headers = tableModel.getHeaders();
79
80         for (int i=0; i<members.length; i++) {
81             if (members[i] instanceof FieldItem) {
82                 cellViewers[i] =
83                     (HTMLViewer)tableModel.getCellRenderer(this,i,factory,context);
84             } else if (members[i] instanceof MethodItem) {
85                 MethodItem method = (MethodItem)members[i];
86                 try {
87                     cellViewers[i] = (HTMLViewer)factory.createView(
88                         method.getName(),
89                         "Method",
90                         new Object JavaDoc[] {substance,method},context);
91                 } catch (Exception JavaDoc e) {
92                     logger.error("Failed to instanciate TableCellRenderer "+
93                                  method.getName()+" for column "+headers[i],e);
94                 }
95             }
96             if (cellViewers[i] instanceof FieldView)
97                 ((FieldView)cellViewers[i]).setAutoUpdate(false);
98             if (cellViewers[i] instanceof CollectionView)
99                 ((CollectionView)cellViewers[i]).setEditor(false);
100         }
101     }
102
103     public void sort() {
104         if (sorter!=null)
105             sorter.sort(this);
106     }
107
108     protected boolean showRefreshButton() {
109         return super.showRefreshButton()
110             || (filterEditors!=null && !filterEditors.isEmpty());
111     }
112
113     public void onRefreshCollection() {
114         if (filterEditors != null) {
115             JacRequest request = ((WebDisplay)context.getDisplay()).getRequest();
116             Iterator JavaDoc it = filterEditors.values().iterator();
117             while (it.hasNext()) {
118                 ObjectChooser chooser = (ObjectChooser)it.next();
119                 chooser.readValue(request.getParameter(chooser.getLabel()));
120             }
121         }
122         checkRange();
123         super.onRefreshCollection();
124     }
125
126     protected void init() {
127         if (model!=null) {
128             sorter = ((ExtendedTableModel)model).getSorter();
129             filter = ((ExtendedTableModel)model).getFilter();
130             if (filter!=null) {
131                 filterEditors = filter.buildFilterEditors(factory,context);
132                 Iterator JavaDoc it = filterEditors.values().iterator();
133                 while (it.hasNext()) {
134                     ObjectChooser chooser = (ObjectChooser)it.next();
135                     chooser.setParentView(this);
136                 }
137             }
138         }
139     }
140
141     // FieldItem -> HTMLViewer
142
Map JavaDoc filterEditors;
143
144     /**
145      * Removes editors of embedded added object
146      */

147     protected void clearFilterEditors() {
148         if (filterEditors!=null) {
149             Iterator JavaDoc it = filterEditors.values().iterator();
150             while (it.hasNext()) {
151                 FieldEditor editor = (FieldEditor)it.next();
152                 context.removeEditor(editor);
153             }
154             filterEditors.clear();
155         }
156     }
157
158     /**
159      * Sorts the collection.
160      *
161      * @param column the index of the column used to sort
162      */

163     public void sort(int column) {
164         sorter.sortByColumn(column, true);
165     }
166
167     // HTMLViewer interface
168

169     public void genHTML(PrintWriter JavaDoc out) throws IOException JavaDoc {
170         MethodItem adder = collection.getAdder();
171         boolean embeddedAdder =
172             adder!=null && GuiAC.getView(adder,itemView.getName()).isEmbedded() &&
173             GuiAC.isAutoCreate(collection);
174         if (model.getRowCount()==0 && !embeddedAdder) {
175             out.println("none");
176         }
177
178         genHeader(out);
179
180         if (model.getRowCount()==0 && !embeddedAdder && filter==null) {
181             return;
182         }
183
184         logger.debug(itemView+".Embedded editors="+itemView.isEmbeddedEditors());
185
186         String JavaDoc[] headers = tableModel.getHeaders();
187
188         out.println("<table class=\"table\">");
189         out.println(" <thead>");
190         out.println(" <tr>");
191         if (showRowNumbers) {
192             out.println(" <th style=\"width:"+
193                         ((""+model.getRowCount()).length())+"ex\" class=\"empty\"></th>");
194         }
195         for (int i=0; i<headers.length; i++) {
196             if (headers[i]!=null) {
197                 out.print(" <th>");
198                 out.print(sortLink(i,headers[i]));
199                 out.println("</th>");
200             } else {
201                 out.print(" <th class=\"empty\"></th>");
202             }
203         }
204         if (viewableItems)
205             out.println(" <th style=\"width:1px\" class=\"empty\"></th>"); // view button
206
if (GuiAC.isRemovable(collection))
207             out.println(" <th style=\"width:1px\" class=\"empty\"></th>"); // remove button
208
out.println(" </tr>");
209         out.println(" </thead>");
210
211         boolean bodyOpened = false;
212
213         Object JavaDoc defaultsObject = null;
214    
215         // Column filters
216
if (filter!=null) {
217             genColumnFilters(out);
218         }
219
220         bodyOpened = false;
221         // Default value editors in the table
222
if (GuiAC.hasEditableDefaultValues(collection) && embeddedAdder) {
223             try {
224                 ClassItem componentType = collection.getComponentType();
225                 defaultsObject = Naming.getObject("defaults."+collection.getLongName());
226                 if (defaultsObject==null) {
227                     Naming.setName("defaults."+collection.getLongName());
228                     defaultsObject = componentType.newInstance();
229                     clearDefaultEditors();
230                 }
231                 out.println(" <tbody class=\"defaultObject\">");
232                 out.println(" <tr class=\"vspace\"></tr>");
233                 out.println(" <tr class=\"defaultObject\">");
234                 FieldItem[] defaultsFields = GuiAC.getDefaultsAttributesOrder(componentType);
235                 if (showRowNumbers) {
236                     out.println(" <td></td>");
237                 }
238                 for (int col=0; col<tableModel.getColumnCount(); col++) {
239                     out.print(" <td>");
240                     MemberItem member = tableModel.getMembers()[col];
241                     if (defaultsFields!=null && !ExtArrays.contains(defaultsFields,member)) {
242                         out.println("</td>");
243                         continue;
244                     }
245                     GuiAC.pushGraphicContext(member);
246                     try {
247                         if (member instanceof FieldItem &&
248                             !(member instanceof CollectionItem))
249                         {
250                             MethodItem setter = ((FieldItem)member).getSetter();
251                             if (GuiAC.isCreationAttribute((FieldItem)member) &&
252                                 setter!=null) {
253                                 // <BAD>WE SHOULD ONLY BUILD THE EDITORS ONCE</BAD>
254
FieldEditor editor = GenericFactory.getEditorComponent(
255                                     factory, context, defaultsObject, setter, 0, true, null);
256                                 defaultsEditors.add(editor);
257                                 context.addEditor(editor);
258                                 ((HTMLViewer)editor).genHTML(out);
259                                 editor.setEmbedded(true);
260                                 //editorContainer.addEditor(editor);
261
//container.addView(editor);
262
}
263                         } else if (member instanceof CollectionItem) {
264                             if (GuiAC.isCreationAttribute((FieldItem)member)) {
265                                 CollectionItem collection = (CollectionItem)member;
266                                 HTMLViewer view = (HTMLViewer)
267                                     GenericFactory.getCollectionPane(
268                                         factory,context,defaultsObject,null,null,collection);
269                                 view.genHTML(out);
270                             }
271                         }
272                     } finally {
273                         GuiAC.popGraphicContext();
274                     }
275                     out.println("</td>");
276                 }
277                 out.println(" <td>"+eventURL("set","onSetDefaults","")+"</td>");
278                 out.println(" </tr>");
279                 out.println(" <tr class=\"vspace\"></tr>");
280                 out.println(" </tbody>");
281             } catch (Exception JavaDoc e) {
282                 e.printStackTrace();
283             }
284         }
285
286         logger.debug("multiLineCollection="+
287                      (multiLineCollection!=null?multiLineCollection.getName():"none"));
288
289         // Actual rows
290
Object JavaDoc currentGroup = null;
291         int groupSpan = 1;
292         MemberItem[] members = tableModel.getMembers();
293         boolean first = true; // First line of multi-line collection or groupBy?
294
int groupIndex = 0;
295         for (int index=startIndex;
296              (!split || index<startIndex+rowsPerPage) && index<model.getRowCount();
297              index++)
298         {
299             Object JavaDoc substance = tableModel.getObject(index);
300             if (!bodyOpened) {
301                 openTBody(out);
302                 bodyOpened = true;
303             }
304             if (multiLineCollection!=null) {
305                 first = true; // First line of multi-line collection ?
306
Collection JavaDoc multi = multiLineCollection.getActualCollectionThroughAccessor(substance);
307                 String JavaDoc rowspan = " rowspan=\""+multi.size()+"\"";
308                 Iterator JavaDoc it = multi.iterator();
309                 if (it.hasNext()) {
310                     while (it.hasNext()) {
311                         if (first)
312                             groupIndex++;
313                         openRow(out,index,groupIndex%2==0);
314                         Object JavaDoc multiSubstance = it.next();
315                         if (first && showRowNumbers) {
316                             out.println(" <td class=\"index\""+rowspan+">"+(index+1)+"</td>");
317                         }
318                         for (int col=0; col<tableModel.getColumnCount(); col++) {
319                             MemberItem member = members[col];
320                             if (member instanceof FieldItem
321                                 && ((FieldItem)member).startsWith(multiLineCollection)) {
322                                 FieldItem multiField =
323                                     ((FieldItem)member).getRelativeField(multiLineCollection);
324                                 genCell(out,index,col,multiSubstance,
325                                         multiField,
326                                         multiField.getThroughAccessor(multiSubstance),
327                                         "");
328                             } else if (first) {
329                                 genCell(out,index,col,substance,member,
330                                         tableModel.getValueAt(index,col),rowspan);
331                             }
332                         }
333                         if (first) {
334                             if (viewableItems)
335                                 genViewCell(out,index,rowspan);
336                             genRemoveCell(out,index,rowspan);
337                         }
338                         out.println(" </tr>");
339                         first = false;
340                     }
341                 } else {
342                     genRow(out,index,substance,members);
343                 }
344             } else if (groupBy!=null) {
345                 Object JavaDoc groupValue = groupBy.getThroughAccessor(substance);
346                 if (currentGroup!=groupValue) {
347                     logger.debug(index+": New group "+groupValue);
348                     currentGroup = groupValue;
349                     groupSpan = 1;
350                     first = true;
351                     for (int i=index+1;
352                          (!split || i<startIndex+rowsPerPage) && i<model.getRowCount();
353                          i++) {
354                         if (groupBy.getThroughAccessor(tableModel.getObject(i))!=currentGroup)
355                             break;
356                         groupSpan++;
357                     }
358                 }
359                 if (first)
360                     groupIndex++;
361                 openRow(out,index,groupIndex%2==1);
362                 if (showRowNumbers) {
363                     out.println(" <td class=\"index\">"+(index+1)+"</td>");
364                 }
365                 for (int col=0; col<tableModel.getColumnCount(); col++) {
366                     MemberItem member = members[col];
367                     if (member instanceof FieldItem
368                         && (((FieldItem)member).startsWith(groupBy) || member==groupBy)) {
369                         if (first) {
370                             String JavaDoc rowspan = groupSpan>1 ? (" rowspan=\""+groupSpan+"\"") : "";
371                             genCell(out,index,col,substance,member,
372                                     tableModel.getValueAt(index,col),rowspan);
373                         }
374                     } else {
375                         genCell(out,index,col,substance,member,
376                                 tableModel.getValueAt(index,col),"");
377                     }
378                 }
379                 if (viewableItems)
380                     genViewCell(out,index,"");
381                 genRemoveCell(out,index,"");
382                 out.println(" </tr>");
383                 first = false;
384             } else {
385                 genRow(out,index,substance,members);
386             }
387
388         }
389         if (bodyOpened) {
390             out.println(" </tbody>");
391             bodyOpened = false;
392         }
393
394         // Embedded adder in the table
395
String JavaDoc focusId = null; // Id of HTML element to focus (if any)
396
if (GuiAC.isAddable(substance,collection)) {
397             try {
398                 ClassItem componentType = collection.getComponentType();
399                 if (embeddedAdder) {
400                     if (addedObject==null) {
401                         addedObject = componentType.newInstance();
402                         EventHandler.initAutocreatedObject(
403                             addedObject,substance,collection);
404                         initAddedObject(addedObject,defaultsObject);
405                         clearEmbeddedEditors(true);
406                     }
407                     out.println(" <tbody>");
408                     out.println(" <tr class=\"vspace\"></tr>");
409                     out.println(" <tr class=\"addedObject\">");
410                     if (showRowNumbers) {
411                         out.println(" <td></td>");
412                     }
413                     for (int col=0; col<tableModel.getColumnCount(); col++) {
414                         out.print(" <td>");
415                         MemberItem member = tableModel.getMembers()[col];
416                         GuiAC.pushGraphicContext(member);
417                         String JavaDoc keyPressEvent =
418                             "return commitFormOnEnter(event,this,'event=onAddEmbedded&amp;source="+getId()+"')\"";
419                         try {
420                             if (member instanceof FieldItem &&
421                                 !(member instanceof CollectionItem))
422                             {
423                                 MethodItem setter = ((FieldItem)member).getSetter();
424                                 if (GuiAC.isCreationAttribute((FieldItem)member) &&
425                                     setter!=null) {
426                                     FieldEditor editor = GenericFactory.getEditorComponent(
427                                         factory, context, addedObject, setter, 0, true, null);
428                                     if (focusId==null)
429                                         focusId = editor.getLabel();
430                                     embeddedEditors.add(editor);
431                                     ((HTMLEditor)editor).setAttribute("onkeypress",keyPressEvent);
432                                     ((HTMLViewer)editor).genHTML(out);
433                                     editor.setEmbedded(true);
434                                     context.addEditor(editor);
435                                     //editorContainer.addEditor(editor);
436
//container.addView(editor);
437
}
438                             } else if (member instanceof CollectionItem) {
439                                 if (GuiAC.isCreationAttribute((FieldItem)member)) {
440                                     CollectionItem coll = (CollectionItem)member;
441                                     CollectionItem index = (CollectionItem)
442                                         coll.getComponentType().getAttribute(GuiAC.INDEXED_FIELD_SELECTOR);
443                                     if (index==null) {
444                                         HTMLViewer view = (HTMLViewer)
445                                             GenericFactory.getCollectionPane(
446                                                 factory,context,addedObject,null,null,coll);
447                                         view.genHTML(out);
448                                     } else {
449                                         FieldEditor editor = factory.createEditor(
450                                             "editor "+Naming.getName(substance)+"."+coll.getName(),
451                                             "IndicesSelector",
452                                             new Object JavaDoc[] {coll,addedObject,
453                                                           new ListModel(coll,addedObject),
454                                                           GuiAC.getView(coll,itemView.getName())},
455                                             context);
456                                         embeddedEditors.add(editor);
457                                         ((HTMLEditor)editor).setAttribute("onkeypress",keyPressEvent);
458                                         ((HTMLViewer)editor).genHTML(out);
459                                         editor.setEmbedded(true);
460                                         context.addEditor(editor);
461                                     }
462                                 }
463                             }
464                         } catch(Exception JavaDoc e) {
465                             logger.error("Failed to gen HTML for embedded object to add, column "+
466                                          tableModel.getHeaders()[col],e);
467                         } finally {
468                             GuiAC.popGraphicContext();
469                         }
470                         out.println("</td>");
471                     }
472                     out.println(" <td>"+eventURL(GuiAC.getLabelAdd(),"onAddEmbedded","")+"</td>");
473                     out.println(" </tr>");
474                     out.println(" </tbody>");
475                 }
476             } catch (Exception JavaDoc e) {
477                 e.printStackTrace();
478             }
479         }
480
481         FieldItem additionalRow = itemView.getAdditionalRow();
482         if (additionalRow!=null) {
483             out.println(" <tbody class=\"additionalRow\">");
484             out.println(" <tr>");
485             if (showRowNumbers) {
486                 out.println(" <td class=\"empty\"></td>");
487             }
488             Object JavaDoc row = additionalRow.getThroughAccessor(substance);
489             for (int col=0; col<tableModel.getColumnCount(); col++) {
490                 MemberItem member = members[col];
491                 if (member instanceof FieldItem && row!=null) {
492                     genCell(out,-1,col,row,member,((FieldItem)member).getThroughAccessor(row),"");
493                 } else {
494                     genCell(out,-1,col,row,member,null,"");
495                 }
496             }
497             if (viewableItems) {
498                 out.println(" <td class=\"empty\"></td>");
499             }
500             if (GuiAC.isRemovable(collection)) {
501                 out.println(" <td class=\"empty\"></td>");
502             }
503             out.println(" </tr>");
504             out.println(" </tbody>");
505         }
506
507         out.println("</table>");
508
509         if (focusId!=null) {
510             out.println("<script type=\"text/javascript\">"+
511                         "element=getElementById('"+focusId+"');"+
512                         "element.focus();"+
513                         "window.scroll(0,10000);"+
514                         "</script>");
515         }
516     }
517
518     protected void genRow(PrintWriter JavaDoc out, int index, Object JavaDoc substance,
519                           MemberItem[] members) {
520         openRow(out,index,index%2==0);
521         if (showRowNumbers) {
522             out.println(" <td class=\"index\">"+(index+1)+"</td>");
523         }
524         for (int col=0; col<tableModel.getColumnCount(); col++) {
525             MemberItem member = members[col];
526             if (multiLineCollection!=null
527                 && member instanceof FieldItem
528                 && ((FieldItem)member).startsWith(multiLineCollection)) {
529                 out.println(" <td></td>");
530             } else {
531                 genCell(out,index,col,substance,member,
532                         tableModel.getValueAt(index,col),"");
533             }
534         }
535         if (viewableItems)
536             genViewCell(out,index,"");
537         genRemoveCell(out,index,"");
538         out.println(" </tr>");
539     }
540
541     protected void genCell(PrintWriter JavaDoc out, int index, int col,
542                            Object JavaDoc substance, MemberItem member, Object JavaDoc value,
543                            String JavaDoc rowspan)
544     {
545         out.print(" <td"+rowspan+">");
546         try {
547             HTMLViewer viewer = null;
548             if (member instanceof FieldItem) {
549                 FieldItem field = (FieldItem)member;
550                 if (itemView.isEmbeddedEditors(field))
551                     viewer = getFieldEditor(field,substance);
552             }
553             if (viewer!=null) {
554                 viewer.genHTML(out);
555             } else {
556                 if (cellViewers[col] instanceof Method) {
557                     out.println(" <a HREF=\""+eventURL("onTableInvoke")+
558                                 "&amp;index="+index+"&amp;method="+
559                                 (member).getName()+"\">"+
560                                 (GuiAC.getLabel(member))+"</a>");
561                   
562                 } else {
563                     FieldView cellViewer = (FieldView)cellViewers[col];
564                     if (cellViewer!=null) {
565                         if (cellViewer instanceof TableCellViewer) {
566                             ((TableCellViewer)cellViewer).setRow(index);
567                             ((TableCellViewer)cellViewer).setColumn(col);
568                         }
569                         if (cellViewer instanceof LinkGenerator) {
570                             ((LinkGenerator)cellViewer).setEnableLinks(itemView.areLinksEnabled());
571                         }
572                         if (cellViewer instanceof CollectionView)
573                             ((CollectionView)cellViewer).updateModel(substance);
574                         else {
575                             cellViewer.setSubstance(substance);
576                             cellViewer.setValue(value);
577                         }
578                         if (cellViewer instanceof ReferenceView) {
579                             ((ReferenceView)cellViewer).setEventURL(
580                                 eventURL("onCellSelection")+"&amp;row="+index+"&amp;col="+col);
581                         }
582                         ((HTMLViewer)cellViewer).genHTML(out);
583                     } else {
584                         if (value!=