KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > comp > renderer > html > HTMLListRenderer


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: HTMLListRenderer.java,v 1.19 2004/02/01 05:16:27 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.comp.renderer.html;
21
22 import java.util.*;
23
24 import org.apache.log4j.*;
25 import org.w3c.dom.*;
26 import org.w3c.dom.html.*;
27
28 import org.enhydra.barracuda.core.comp.*;
29 import org.enhydra.barracuda.core.comp.renderer.*;
30 import org.enhydra.barracuda.core.util.dom.*;
31 import org.enhydra.barracuda.core.view.*;
32 import org.enhydra.barracuda.plankton.*;
33
34 /**
35  * This class handles the default rendering of a list in an HTML view.
36  */

37 public class HTMLListRenderer extends HTMLComponentRenderer {
38
39     protected static final Logger logger = Logger.getLogger(HTMLListRenderer.class.getName());
40     
41     protected BList blist = null;
42     protected ListModel model = null;
43     protected EnabledHelper eh = new EnabledHelper();
44     
45     /**
46      * The purpose of this method is for a renderer to provide
47      * a default node (if none exists). This component currently
48      * does not provide a default, so it throws an UnsupportedFormatException
49      * instead.
50      *
51      * @param doc the master Document which can be used to create elements
52      * from scratch
53      * @param comp the component that we're dealing with for the current request
54      * @param vc the view context for the current request
55      * @return a default node (created from scratch)
56      * @throws UnsupportedFormatException if the renderer has no default node
57      */

58 //csc_110501.1 public Node createDefaultNode(Document doc, ViewContext vc) throws UnsupportedFormatException;
59
public Node createDefaultNode(Document doc, BComponent comp, ViewContext vc) throws UnsupportedFormatException { //csc_110501.1
60
// throw new UnsupportedFormatException("Cannot create default node");
61
//ask the renderer to create the default Node
62
Node templateNode = vc.getTemplateNode();
63         Node defaultNode = templateNode.cloneNode(true);
64         if (logger.isInfoEnabled()) logger.info("Creating default node:"+defaultNode);
65         return defaultNode;
66     }
67
68     /**
69      *
70      */

71     public void renderComponent(BComponent comp, View view, ViewContext vc) throws RenderException {
72         //make sure the component is a list component
73
if (!(comp instanceof BList)) throw new NoSuitableRendererException("This renderer can only render BList components; comp is of type:"+comp.getClass().getName());
74         blist = (BList) comp;
75         model = blist.getModel();
76         Node node = view.getNode();
77         Node origTemplateNode = vc.getTemplateNode(); //csc_100901.4
78

79         //show what we're doing
80
if (logger.isDebugEnabled()) showNodeInterfaces(view, logger);
81
82         //first, allow the parent class to do anything it needs to
83
super.renderComponent(comp, view, vc);
84
85         //HTMLElement Interface
86
//---------------------
87
//Supported Elements:
88

89         //defs: fontstyle = (TT|I|B|BIG|SMALL)
90
//defs: phrase = (EM|STRONG|DFN|CODE|SAMP|KBD|VAR|CITE|ABBR|ACRONYM)
91
//defs: special = (A|IMG|OBJECT|BR|SCRIPT|MAP|Q|SUB|SUP|SPAN|BDO)
92
//defs: formctrl = (INPUT|SELECT|TEXTAREA|LABEL|BUTTON)
93
//defs: block = (P|heading|list|preformatted|DL|DIV|NOSCRIPT|BLOCKQUOTE|
94
// FORM|HR|TABLE|FIELDSET|ADDRESS)
95
//defs: inline = (pcdata|fontstyle|phrase|special|formctrl)
96
//defs: flow = (block|inline)
97

98         //list structures
99
//..HTMLDListElement <DL> (DT|DD)
100
//..HTMLFieldSetElement <FIELDSET> (pcdata|LEGEND|flow)
101
//..HTMLFrameSetElement <FRAMESET> ((FRAMESET|FRAME)+ & NOFRAMES?)
102
//..HTMLMapElement <MAP> (block|AREA)
103
//..HTMLOList <OL> (LI)
104
//..HTMLUList <UL> (LI)
105
//..HTMLOptGroupElement <OPTGROUP> (OPTION)
106
//..HTMLSelectElement <SELECT> (OPTGROUP|OPTION)
107
//..HTMLTableColElement <COLGROUP> (COL).
108
//..HTMLTableElement <TABLE> (CAPTION?, (COL*|COLGROUP*), THEAD?,
109
// TFOOT?, TBODY+)
110
//..HTMLTableSectionElement <THEAD> (TR)
111
// <TFOOT> (TR)
112
// <TBODY> (TR)
113
//..HTMLTableRowElement <TR> (TH|TD)
114

115         //text containers
116
//..HTMLHeadingElement <H1>..<H6> (inline)
117
//..HTMLLabelElement <LABEL> (inline)
118
//..HTMLLegendElement <LEGEND> (inline)
119
//..HTMLLIElement <LI> (flow)
120
//..HTMLModElement <INS>,<DEL> (flow)
121
//..HTMLObjectElement <OBJECT> (PARAM|flow)
122
//..HTMLOptionElement <OPTION> (pcdata)
123
//..HTMLParagraphElement <P> (inline)
124
//..HTMLPreElement <PRE> (inline, excl.IMG|OBJECT|BIG|SMALL|SUB|
125
// SUP)
126
//..HTMLQuoteElement <Q> (inline)
127
//..HTMLTableCaptionElement <CAPTION> (inline)
128
//..HTMLTableCellElement <TH>,<TD> (flow)
129
//..HTMLTextAreaElement <TEXTAREA> (pcdata)
130

131         //
132
//Unsupported Elements:
133
//..HTMLAnchorElement, HTMLAppletElement (deprec in HTML 4.0), HTMLAreaElement,
134
//....HTMLBaseElement, HTMLBaseFontElement, HTMLBodyElement, HTMLBRElement,
135
//....HTMLButtonElement, HTMLDirectoryElement (deprec in HTML 4.0),
136
//....HTMLDivElement, HTMLFontElement, HTMLFormElement, HTMLFrameElement,
137
//....HTMLHeadElement, HTMLIFrameElement, HTMLImageElement,
138
//....HTMLIsIndexElement (deprec in HTML 4.0), HTMLInputElement, HTMLHRElement,
139
//....HTMLHtmlElement, HTMLLinkElement, HTMLMenuElement (deprec in HTML 4.0),
140
//....HTMLMetaElement, HTMLParamElement, HTMLScriptElement, HTMLTitleElement,
141
//....HTMLStyleElement,
142
if (node instanceof HTMLElement) {
143
144             try {
145                 if (logger.isInfoEnabled()) logger.info("Rendering list component...");
146
147                 //start by removing all children from the node
148
while (node.hasChildNodes()) {
149                     node.removeChild(node.getFirstChild());
150                 }
151
152                 //give the model a chance to initialize
153
model.setViewContext(vc);
154                 model.resetModel();
155                 vc.putState(ViewContext.TEMPLATE_NODE, node);
156
157                 //now get all the items from the model and add them as children
158
ElementFactory ef = view.getElementFactory();
159                 for (int i=0,max=model.getSize(); i<max; i++) {
160                     //get the next item
161
// Object item = model.getItemAt(i, vc);
162
Object JavaDoc item = model.getItemAt(i);
163
164                     //if the item is actually a List
165
if (item instanceof List) {
166                         Iterator it = ((List) item).iterator();
167                         while (it.hasNext()) {
168                             addItemToList(node, vc, ef, it.next(), 1);
169                         }
170                     //if the item is actually an array of objects
171
} else if (item instanceof Object JavaDoc[]) {
172                         Object JavaDoc itemArr[] = (Object JavaDoc[]) item;
173                         for (int j=0,jmax=itemArr.length; j<jmax; j++) {
174                             addItemToList(node, vc, ef, itemArr[j], 1);
175                         }
176                     //if its just a plain old item
177
} else {
178                         addItemToList(node, vc, ef, item, 1);
179                     }
180                 }
181 /*
182                 populateListFromModel(node, view, vc);
183 */

184                 
185             } catch (DOMException e) {
186                 if (logger.isInfoEnabled()) logger.info("Node does not support children...rendering list as text", e);
187             
188                 //convert the model to a string
189
String JavaDoc s = model.toString();
190                 
191                 //now try binding the string to the node via a BText component
192
// BText textComp = new BText(s, new DefaultView(node));
193
BText textComp = new BText(s);
194                 textComp.setView(new DefaultView(node));
195
196                 //now add the comp as a temporary child (by doing this, we ensure that
197
//the child will get rendered as well. After rendering, we'll remove
198
//the child from the hierarchy, so as to return to our original state)
199
// if (tempChildren==null) tempChildren = new ArrayList();
200
// tempChildren.add(textComp);
201
// this.add(textComp);
202
blist.addStepChild(textComp);
203             } finally {
204 //csc_100901.4 vc.putState(ViewContext.TEMPLATE_NODE, null);
205
vc.putState(ViewContext.TEMPLATE_NODE, origTemplateNode); //csc_100901.4
206
model.setViewContext(null);
207             }
208             
209                 
210         } else {
211             String JavaDoc errmsg = "Node does not implement HTMLElement and cannot be rendered: "+node;
212             logger.warn(errmsg);
213             throw new NoSuitableRendererException(errmsg);
214         }
215         
216         //finally, make sure we reflect the components enabled/disabled status
217
eh.setEnabled(node, comp.isEnabled());
218     }
219     
220 /*
221     protected void populateListFromModel(Node node, View view, ViewContext vc) throws RenderException {
222         //now get all the items from the model and add them as children
223         ElementFactory ef = view.getElementFactory();
224         for (int i=0,max=model.getSize(); i<max; i++) {
225             //get the next item
226             Object item = model.getItemAt(i, vc);
227
228             //handle it
229             handleNextItem(node, ef, item);
230         }
231     }
232
233     protected void handleNextItem(Node node, ElementFactory ef, Object item) throws RenderException {
234         //if the item is actually a List
235         if (item instanceof List) {
236             Iterator it = ((List) item).iterator();
237             while (it.hasNext()) {
238                 addItemToList(node, ef, it.next(), 1);
239             }
240         //if the item is actually an array of objects
241         } else if (item instanceof Object[]) {
242             Object itemArr[] = (Object[]) item;
243             for (int j=0,jmax=itemArr.length; j<jmax; j++) {
244                 addItemToList(node, ef, itemArr[j], 1);
245             }
246         //if its just a plain old item
247         } else {
248             addItemToList(node, ef, item, 1);
249         }
250     }
251 */

252     protected void addItemToList(Node node, ViewContext vc, ElementFactory ef, Object JavaDoc item, int depth) throws RenderException {
253         if (item == null) {
254             //jrk_20030411.3 added null check and logger warning
255
logger.warn("Ignoring attempt to add null item to the list");
256         } else {
257             //show what the item implements
258
if (logger.isDebugEnabled()) {
259                 //csc_102601.1_start - this causes a null pointer exception if
260
//the item happens to be a BComponent which isnot yet bound to a view
261
// if (logger.isDebugEnabled()) logger.debug("item "+item+" implements the following interfaces:");
262
if (logger.isDebugEnabled()) {
263                     if (item instanceof BComponent) logger.debug("item " + item.getClass().getName() + "@" + Integer.toHexString(item.hashCode()) + " implements the following interfaces:");
264                     else logger.debug("item "+item+" implements the following interfaces:");
265                 }
266                 //csc_102601.1_end
267
Iterator it = Classes.getAllInterfaces(item).iterator();
268                 while (it.hasNext()) {
269                     Object JavaDoc o = it.next();
270                     if (logger.isDebugEnabled()) logger.debug(o.toString());
271                 }
272             }
273     
274             //get it back into the DOM
275
//..BComponent
276
if (item instanceof BComponent) {
277                 //add in the Node for each view
278
if (logger.isDebugEnabled()) logger.debug("Getting next BComponent item: "+item+"...");
279                 BComponent wcomp = (BComponent) item;
280     
281     /*
282     //Orig
283                 Iterator it = wcomp.getViews().iterator();
284                 while (it.hasNext()) {
285                     View view = (View) it.next();
286                     addChildToParent(node, view.getNode());
287                 }
288     */

289                 //if the component needs a default view create one for it...
290
//csc_110501.1 List views = wcomp.getViews();
291
//csc_110501.1 if (views==null || views.size()<1) {
292
if (!wcomp.hasViews()) { //csc_110501.1
293
//get the format type and the doc from the view context
294
FormatType ft = vc.getViewCapabilities().getFormatType();
295                     Document doc = vc.getElementFactory().getDocument();
296     
297                     try {
298                         //get the appropriate renderer by looking up the
299
//DOM class associated with the given format type
300
Renderer r = wcomp.getRenderer(ft.getDOMClass());
301                         
302     
303     //csc_110501.1_start
304
/*
305                         //ask the renderer to create the default Node
306                         Node n = r.createDefaultNode(doc, vc);
307                         addChildToParent(node, n);
308                         
309                         //finally create a view on the resulting node and add it in
310                         wcomp.addTempView(new DefaultView(n));
311                         wcomp.invalidate();
312     */

313                         //ask the renderer to create the default Node
314
Node n = r.createDefaultNode(doc, wcomp, vc); //csc_110501.1
315
addChildToParent(node, n);
316                         
317                         //if the component still needs a default view create one for it...
318
if (!wcomp.hasViews()) wcomp.addTempView(new DefaultView(n));
319                         wcomp.invalidate();
320     //csc_110501.1_end
321

322                     } catch (RenderException e) {
323                         logger.warn("Unable to create default view:", e);
324                     } catch (DOMException e) {
325                         logger.warn("Unable to create default view:", e);
326                     }
327                     
328                 //if the component being returned is already bound to views,
329
//just add in the nodes that back the views
330
//csc_110501.1 } else if (views!=null) {
331
//csc_110501.1 Iterator it = views.iterator();
332
} else { //csc_110501.1
333
Iterator it = wcomp.getViews().iterator(); //csc_110501.1
334
while (it.hasNext()) {
335                         View view = (View) it.next();
336                         addChildToParent(node, view.getNode());
337                     }
338                 }
339                 
340                 //now add the comp as a temporary child (by doing this, we ensure that
341
//the child will get rendered as well. After rendering, we'll remove
342
//the child from the hierarchy, so as to return to our original state)
343
// if (tempChildren==null) tempChildren = new ArrayList();
344
// tempChildren.add(wcomp);
345
// this.add(wcomp);
346
blist.addStepChild(wcomp);
347     
348             //..Nodes
349
} else if (item instanceof Node) {
350                 if (logger.isDebugEnabled()) logger.debug("Getting next Node item: "+item+"...");
351     // node.appendChild((Node) item);
352
addChildToParent(node, (Node) item);
353             
354             //..Strings
355
} else {
356                 if (logger.isDebugEnabled()) logger.debug("Getting next String item: "+item+"...");
357     //by making ItemMap implement toString(), we don't even have to explicitly reference it here...
358
// String s = null;
359
// if (item instanceof ItemMap) s = ((ItemMap) item).getValue().toString();
360
// else s = item.toString();
361
String JavaDoc s = item.toString();
362                 
363                 //get the template for this particular node
364
Node templateNode = ef.getDefaultElement();
365                 Node newNode = null;
366                 if (templateNode!=null) {
367                     //create the new node by cloning
368
newNode = templateNode.cloneNode(true);
369                 } else {
370                     //create the new node from scratch
371
String JavaDoc targetEl = null;
372                     if (node instanceof HTMLDListElement) targetEl = "DT";
373                     else if (node instanceof HTMLOListElement) targetEl = "LI";
374                     else if (node instanceof HTMLOptGroupElement) targetEl = "OPTION";
375                     else if (node instanceof HTMLSelectElement) targetEl = "OPTION";
376                     else if (node instanceof HTMLTableColElement) targetEl = "COL";
377                     else if (node instanceof HTMLTableRowElement) targetEl = "TD";
378                     else if (node instanceof HTMLUListElement) targetEl = "LI";
379                     else throw new DOMException((short) 0, "Unsupported List node");
380                     newNode = node.getOwnerDocument().createElement(targetEl);
381                 }
382                 
383                 //now populate the new node and add it back in
384
if (newNode!=null) {
385     // BText textComp = new BText(s, new DefaultView(newNode));
386
BText textComp = new BText(s);
387                     textComp.setView(new DefaultView(newNode));
388     // if (tempChildren==null) tempChildren = new ArrayList();
389
// tempChildren.add(textComp);
390
// this.add(textComp);
391
blist.addStepChild(textComp);
392     // node.appendChild(newNode);
393
addChildToParent(node, newNode);
394                     
395                 } else {
396                     throw new InvalidNodeException("Unable to create a new Text node");
397                 }
398             }
399         }
400     }
401     
402 }
Popular Tags