~ubuntu-branches/ubuntu/trusty/libstruts1.2-java/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/struts-faces/src/java/org/apache/struts/faces/renderer/AbstractRenderer.java

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Vandyck
  • Date: 2004-11-19 15:35:25 UTC
  • Revision ID: james.westby@ubuntu.com-20041119153525-mdu08a76z4zo67xt
Tags: upstream-1.2.4
ImportĀ upstreamĀ versionĀ 1.2.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2002,2004 The Apache Software Foundation.
 
3
 * 
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 * 
 
8
 *      http://www.apache.org/licenses/LICENSE-2.0
 
9
 * 
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
package org.apache.struts.faces.renderer;
 
18
 
 
19
 
 
20
import java.io.IOException;
 
21
import java.util.Iterator;
 
22
import java.util.Map;
 
23
 
 
24
import javax.faces.application.FacesMessage;
 
25
import javax.faces.component.EditableValueHolder;
 
26
import javax.faces.component.UIComponent;
 
27
import javax.faces.component.ValueHolder;
 
28
import javax.faces.context.FacesContext;
 
29
import javax.faces.context.ResponseWriter;
 
30
import javax.faces.convert.Converter;
 
31
import javax.faces.convert.ConverterException;
 
32
import javax.faces.el.ValueBinding;
 
33
import javax.faces.render.Renderer;
 
34
 
 
35
import org.apache.commons.logging.Log;
 
36
import org.apache.commons.logging.LogFactory;
 
37
 
 
38
 
 
39
/**
 
40
 * <p>Abstract base class for concrete implementations of
 
41
 * <code>javax.faces.render.Renderer</code> for the
 
42
 * <em>Struts-Faces Integration Library</em>.</p>
 
43
 *
 
44
 * @version $Revision: 1.8 $ $Date: 2004/06/09 02:28:28 $
 
45
 */
 
46
 
 
47
public abstract class AbstractRenderer extends Renderer {
 
48
 
 
49
 
 
50
    // -------------------------------------------------------- Static Variables
 
51
 
 
52
 
 
53
    private static final Log log =
 
54
        LogFactory.getLog(AbstractRenderer.class);
 
55
 
 
56
 
 
57
    // -------------------------------------------------------- Renderer Methods
 
58
 
 
59
 
 
60
    /**
 
61
     * <p>Decode any new state of the specified <code>UIComponent</code>
 
62
     * from the request contained in the specified <code>FacesContext</code>,
 
63
     * and store that state on the <code>UIComponent</code>.</p>
 
64
     *
 
65
     * <p>The default implementation calls <code>setSubmittedValue()</code>
 
66
     * unless this component has a boolean <code>disabled</code> or
 
67
     * <code>readonly</code> attribute that is set to <code>true</code>.</p>
 
68
     *
 
69
     * @param context <code>FacesContext</code> for the current request
 
70
     * @param component <code>UIComponent</code> to be decoded
 
71
     *
 
72
     * @exception NullPointerException if <code>context</code> or
 
73
     *  <code>component</code> is <code>null</code>
 
74
     */
 
75
    public void decode(FacesContext context, UIComponent component) {
 
76
 
 
77
        // Enforce NPE requirements in the Javadocs
 
78
        if ((context == null) || (component == null)) {
 
79
            throw new NullPointerException();
 
80
        }
 
81
 
 
82
        // Disabled or readonly components are not decoded
 
83
        if (isDisabled(component) || isReadOnly(component)) {
 
84
            return;
 
85
        }
 
86
 
 
87
        // Save submitted value on EditableValueHolder components
 
88
        if (component instanceof EditableValueHolder) {
 
89
            setSubmittedValue(context, component);
 
90
        }
 
91
        
 
92
    }
 
93
 
 
94
 
 
95
    /**
 
96
     * <p>Render the beginning of the specified <code>UIComponent</code>
 
97
     * to the output stream or writer associated with the response we are
 
98
     * creating.</p>
 
99
     *
 
100
     * <p>The default implementation calls <code>renderStart()</code> and
 
101
     * <code>renderAttributes()</code>.</p>
 
102
     *
 
103
     * @param context <code>FacesContext</code> for the current request
 
104
     * @param component <code>UIComponent</code> to be decoded
 
105
     *
 
106
     * @exception NullPointerException if <code>context</code> or
 
107
     *  <code>component</code> is <code>null</code>
 
108
     *
 
109
     * @exception IOException if an input/output error occurs
 
110
     */
 
111
    public void encodeBegin(FacesContext context, UIComponent component)
 
112
        throws IOException {
 
113
 
 
114
        // Enforce NPE requirements in the Javadocs
 
115
        if ((context == null) || (component == null)) {
 
116
            throw new NullPointerException();
 
117
        }
 
118
 
 
119
        if (log.isTraceEnabled()) {
 
120
            log.trace("encodeBegin(id=" + component.getId() +
 
121
                      ", family=" + component.getFamily() +
 
122
                      ", rendererType=" + component.getRendererType() + ")");
 
123
        }
 
124
 
 
125
        // Render the element and attributes for this component
 
126
        ResponseWriter writer = context.getResponseWriter();
 
127
        renderStart(context, component, writer);
 
128
        renderAttributes(context, component, writer);
 
129
 
 
130
    }
 
131
 
 
132
 
 
133
    /**
 
134
     * <p>Render the children of the specified <code>UIComponent</code>
 
135
     * to the output stream or writer associated with the response we are
 
136
     * creating.</p>
 
137
     *
 
138
     * <p>The default implementation iterates through the children of
 
139
     * this component and renders them.</p>
 
140
     *
 
141
     * @param context <code>FacesContext</code> for the current request
 
142
     * @param component <code>UIComponent</code> to be decoded
 
143
     *
 
144
     * @exception NullPointerException if <code>context</code> or
 
145
     *  <code>component</code> is <code>null</code>
 
146
     *
 
147
     * @exception IOException if an input/output error occurs
 
148
     */
 
149
    public void encodeChildren(FacesContext context, UIComponent component)
 
150
        throws IOException {
 
151
 
 
152
        if (context == null || component == null) {
 
153
            throw new NullPointerException();
 
154
        }
 
155
 
 
156
        if (log.isTraceEnabled()) {
 
157
            log.trace("encodeChildren(id=" + component.getId() +
 
158
                      ", family=" + component.getFamily() +
 
159
                      ", rendererType=" + component.getRendererType() + ")");
 
160
        }
 
161
        Iterator kids = component.getChildren().iterator();
 
162
        while (kids.hasNext()) {
 
163
            UIComponent kid = (UIComponent) kids.next();
 
164
            kid.encodeBegin(context);
 
165
            if (kid.getRendersChildren()) {
 
166
                kid.encodeChildren(context);
 
167
            }
 
168
            kid.encodeEnd(context);
 
169
        }
 
170
        if (log.isTraceEnabled()) {
 
171
            log.trace("encodeChildren(id=" + component.getId() + ") end");
 
172
        }
 
173
 
 
174
    }
 
175
 
 
176
 
 
177
    /**
 
178
     * <p>Render the ending of the specified <code>UIComponent</code>
 
179
     * to the output stream or writer associated with the response we are
 
180
     * creating.</p>
 
181
     *
 
182
     * <p>The default implementation calls <code>renderEnd()</code>.</p>
 
183
     *
 
184
     * @param context <code>FacesContext</code> for the current request
 
185
     * @param component <code>UIComponent</code> to be decoded
 
186
     *
 
187
     * @exception NullPointerException if <code>context</code> or
 
188
     *  <code>component</code> is <code>null</code>
 
189
     *
 
190
     * @exception IOException if an input/output error occurs
 
191
     */
 
192
    public void encodeEnd(FacesContext context, UIComponent component)
 
193
        throws IOException {
 
194
 
 
195
        // Enforce NPE requirements in the Javadocs
 
196
        if ((context == null) || (component == null)) {
 
197
            throw new NullPointerException();
 
198
        }
 
199
 
 
200
        if (log.isTraceEnabled()) {
 
201
            log.trace("encodeEnd(id=" + component.getId() +
 
202
                      ", family=" + component.getFamily() +
 
203
                      ", rendererType=" + component.getRendererType() + ")");
 
204
        }
 
205
 
 
206
        // Render the element closing for this component
 
207
        ResponseWriter writer = context.getResponseWriter();
 
208
        renderEnd(context, component, writer);
 
209
 
 
210
    }
 
211
 
 
212
 
 
213
    // --------------------------------------------------------- Package Methods
 
214
 
 
215
 
 
216
    // ------------------------------------------------------- Protected Methods
 
217
 
 
218
 
 
219
    /**
 
220
     * <p>Render nested child components by invoking the encode methods
 
221
     * on those components, but only when the <code>rendered</code>
 
222
     * property is <code>true</code>.</p>
 
223
     */
 
224
    protected void encodeRecursive(FacesContext context, UIComponent component)
 
225
        throws IOException {
 
226
 
 
227
        // suppress rendering if "rendered" property on the component is
 
228
        // false.
 
229
        if (!component.isRendered()) {
 
230
            return;
 
231
        }
 
232
 
 
233
        // Render this component and its children recursively
 
234
        if (log.isTraceEnabled()) {
 
235
            log.trace("encodeRecursive(id=" + component.getId() +
 
236
                      ", family=" + component.getFamily() +
 
237
                      ", rendererType=" + component.getRendererType() +
 
238
                      ") encodeBegin");
 
239
        }
 
240
        component.encodeBegin(context);
 
241
        if (component.getRendersChildren()) {
 
242
            if (log.isTraceEnabled()) {
 
243
                log.trace("encodeRecursive(id=" + component.getId() +
 
244
                          ") delegating");
 
245
            }
 
246
            component.encodeChildren(context);
 
247
        } else {
 
248
            if (log.isTraceEnabled()) {
 
249
                log.trace("encodeRecursive(id=" + component.getId() +
 
250
                          ") recursing");
 
251
            }
 
252
            Iterator kids = component.getChildren().iterator();
 
253
            while (kids.hasNext()) {
 
254
                UIComponent kid = (UIComponent) kids.next();
 
255
                encodeRecursive(context, kid);
 
256
            }
 
257
        }
 
258
        if (log.isTraceEnabled()) {
 
259
            log.trace("encodeRecursive(id=" + component.getId() + ") encodeEnd");
 
260
        }
 
261
        component.encodeEnd(context);
 
262
 
 
263
    }
 
264
 
 
265
 
 
266
    /**
 
267
     * <p>Return <code>true</code> if the specified component is disabled.</p>
 
268
     *
 
269
     * @param component <code>UIComponent</code> to be checked
 
270
     */
 
271
    protected boolean isDisabled(UIComponent component) {
 
272
 
 
273
        Object disabled = component.getAttributes().get("disabled");
 
274
        if (disabled == null) {
 
275
            return (false);
 
276
        }
 
277
        if (disabled instanceof String) {
 
278
            return (Boolean.valueOf((String) disabled).booleanValue());
 
279
        } else {
 
280
            return (disabled.equals(Boolean.TRUE));
 
281
        }
 
282
 
 
283
    }
 
284
 
 
285
 
 
286
    /**
 
287
     * <p>Return <code>true</code> if the specified component is read only.</p>
 
288
     *
 
289
     * @param component <code>UIComponent</code> to be checked
 
290
     */
 
291
    protected boolean isReadOnly(UIComponent component) {
 
292
 
 
293
        Object readonly = component.getAttributes().get("readonly");
 
294
        if (readonly == null) {
 
295
            return (false);
 
296
        }
 
297
        if (readonly instanceof String) {
 
298
            return (Boolean.valueOf((String) readonly).booleanValue());
 
299
        } else {
 
300
            return (readonly.equals(Boolean.TRUE));
 
301
        }
 
302
 
 
303
    }
 
304
 
 
305
 
 
306
    /**
 
307
     * <p>Render the element attributes for the generated markup related to this
 
308
     * component.  Simple renderers that create a single markup element
 
309
     * for this component should override this method and include calls to
 
310
     * to <code>writeAttribute()</code> and <code>writeURIAttribute</code>
 
311
     * on the specified <code>ResponseWriter</code>.</p>
 
312
     *
 
313
     * <p>The default implementation does nothing.</p>
 
314
     *
 
315
     * @param context <code>FacesContext</code> for the current request
 
316
     * @param component <code>EditableValueHolder</code> component whose
 
317
     *  submitted value is to be stored
 
318
     * @param writer <code>ResponseWriter</code> to which the element
 
319
     *  start should be rendered
 
320
     *
 
321
     * @exception IOException if an input/output error occurs
 
322
     */
 
323
    protected void renderAttributes(FacesContext context, UIComponent component,
 
324
                                    ResponseWriter writer) throws IOException {
 
325
 
 
326
    }
 
327
 
 
328
 
 
329
    /**
 
330
     * <p>Render the element end for the generated markup related to this
 
331
     * component.  Simple renderers that create a single markup element
 
332
     * for this component should override this method and include a call
 
333
     * to <code>endElement()</code> on the specified
 
334
     * <code>ResponseWriter</code>.</p>
 
335
     *
 
336
     * <p>The default implementation does nothing.</p>
 
337
     *
 
338
     * @param context <code>FacesContext</code> for the current request
 
339
     * @param component <code>EditableValueHolder</code> component whose
 
340
     *  submitted value is to be stored
 
341
     * @param writer <code>ResponseWriter</code> to which the element
 
342
     *  start should be rendered
 
343
     *
 
344
     * @exception IOException if an input/output error occurs
 
345
     */
 
346
    protected void renderEnd(FacesContext context, UIComponent component,
 
347
                             ResponseWriter writer) throws IOException {
 
348
 
 
349
    }
 
350
 
 
351
 
 
352
    /**
 
353
     * <p>Render any boolean attributes on the specified list that have
 
354
     * <code>true</code> values on the corresponding attribute of the
 
355
     * specified <code>UIComponent</code>.</p>
 
356
     *
 
357
     * @param context <code>FacesContext</code> for the current request
 
358
     * @param component <code>EditableValueHolder</code> component whose
 
359
     *  submitted value is to be stored
 
360
     * @param writer <code>ResponseWriter</code> to which the element
 
361
     *  start should be rendered
 
362
     * @param names List of attribute names to be passed through
 
363
     *
 
364
     * @exception IOException if an input/output error occurs
 
365
     */
 
366
    protected void renderBoolean(FacesContext context,
 
367
                                 UIComponent component,
 
368
                                 ResponseWriter writer,
 
369
                                 String names[]) throws IOException {
 
370
 
 
371
        if (names == null) {
 
372
            return;
 
373
        }
 
374
        Map attributes = component.getAttributes();
 
375
        boolean flag;
 
376
        Object value;
 
377
        for (int i = 0; i < names.length; i++) {
 
378
            value = attributes.get(names[i]);
 
379
            if (value != null) {
 
380
                if (value instanceof String) {
 
381
                    flag = Boolean.valueOf((String) value).booleanValue();
 
382
                } else {
 
383
                    flag = Boolean.valueOf(value.toString()).booleanValue();
 
384
                }
 
385
                if (flag) {
 
386
                    writer.writeAttribute(names[i], names[i], names[i]);
 
387
                    flag = false;
 
388
                }
 
389
            }
 
390
        }
 
391
 
 
392
    }
 
393
 
 
394
 
 
395
    /**
 
396
     * <p>Render any attributes on the specified list directly to the
 
397
     * specified <code>ResponseWriter</code> for which the specified
 
398
     * <code>UIComponent</code> has a non-<code>null</code> attribute value.
 
399
     * This method may be used to "pass through" commonly used attribute
 
400
     * name/value pairs with a minimum of code.</p>
 
401
     *
 
402
     * @param context <code>FacesContext</code> for the current request
 
403
     * @param component <code>EditableValueHolder</code> component whose
 
404
     *  submitted value is to be stored
 
405
     * @param writer <code>ResponseWriter</code> to which the element
 
406
     *  start should be rendered
 
407
     * @param names List of attribute names to be passed through
 
408
     *
 
409
     * @exception IOException if an input/output error occurs
 
410
     */
 
411
    protected void renderPassThrough(FacesContext context,
 
412
                                     UIComponent component,
 
413
                                     ResponseWriter writer,
 
414
                                     String names[]) throws IOException {
 
415
 
 
416
        if (names == null) {
 
417
            return;
 
418
        }
 
419
        Map attributes = component.getAttributes();
 
420
        Object value;
 
421
        for (int i = 0; i < names.length; i++) {
 
422
            value = attributes.get(names[i]);
 
423
            if (value != null) {
 
424
                if (value instanceof String) {
 
425
                    writer.writeAttribute(names[i], (String) value, names[i]);
 
426
                } else {
 
427
                    writer.writeAttribute(names[i], value.toString(), names[i]);
 
428
                }
 
429
            }
 
430
        }
 
431
 
 
432
    }
 
433
 
 
434
 
 
435
    /**
 
436
     * <p>Render the element start for the generated markup related to this
 
437
     * component.  Simple renderers that create a single markup element
 
438
     * for this component should override this method and include a call
 
439
     * to <code>startElement()</code> on the specified
 
440
     * <code>ResponseWriter</code>.</p>
 
441
     *
 
442
     * <p>The default implementation does nothing.</p>
 
443
     *
 
444
     * @param context <code>FacesContext</code> for the current request
 
445
     * @param component <code>EditableValueHolder</code> component whose
 
446
     *  submitted value is to be stored
 
447
     * @param writer <code>ResponseWriter</code> to which the element
 
448
     *  start should be rendered
 
449
     *
 
450
     * @exception IOException if an input/output error occurs
 
451
     */
 
452
    protected void renderStart(FacesContext context, UIComponent component,
 
453
                               ResponseWriter writer) throws IOException {
 
454
 
 
455
    }
 
456
 
 
457
 
 
458
    /**
 
459
     * <p>If a submitted value was included on this request, store it in the
 
460
     * component as appropriate.</p>
 
461
     *
 
462
     * <p>The default implementation determines whether this component
 
463
     * implements <code>EditableValueHolder</code>.  If so, it checks for a
 
464
     * request parameter with the same name as the <code>clientId</code>
 
465
     * of this <code>UIComponent</code>.  If there is such a parameter, its
 
466
     * value is passed (as a String) to the <code>setSubmittedValue()</code>
 
467
     * method on the <code>EditableValueHolder</code> component.</p>
 
468
     *
 
469
     * @param context <code>FacesContext</code> for the current request
 
470
     * @param component <code>EditableValueHolder</code> component whose
 
471
     *  submitted value is to be stored
 
472
     */
 
473
    protected void setSubmittedValue
 
474
        (FacesContext context, UIComponent component) {
 
475
 
 
476
        if (!(component instanceof EditableValueHolder)) {
 
477
            return;
 
478
        }
 
479
        String clientId = component.getClientId(context);
 
480
        Map parameters = context.getExternalContext().getRequestParameterMap();
 
481
        if (parameters.containsKey(clientId)) {
 
482
            if (log.isTraceEnabled()) {
 
483
                log.trace("setSubmittedValue(" + clientId + "," +
 
484
                          (String) parameters.get(clientId));
 
485
            }
 
486
            component.getAttributes().put("submittedValue",
 
487
                                          (String) parameters.get(clientId));
 
488
        }
 
489
 
 
490
    }
 
491
 
 
492
 
 
493
    // --------------------------------------------------------- Private Methods
 
494
 
 
495
 
 
496
    /**
 
497
     * <p>Decode the current state of the specified UIComponent from the
 
498
     * request contained in the specified <code>FacesContext</code>, and
 
499
     * attempt to convert this state information into an object of the
 
500
     * type equired for this component.</p>
 
501
     *
 
502
     * @param context FacesContext for the request we are processing
 
503
     * @param component UIComponent to be decoded
 
504
     *
 
505
     * @exception NullPointerException if context or component is null
 
506
     */
 
507
    /*
 
508
    public void decode(FacesContext context, UIComponent component) {
 
509
 
 
510
        // Enforce NPE requirements in the Javadocs
 
511
        if ((context == null) || (component == null)) {
 
512
            throw new NullPointerException();
 
513
        }
 
514
 
 
515
        // Only input components need to be decoded
 
516
        if (!(component instanceof UIInput)) {
 
517
            return;
 
518
        }
 
519
        UIInput input = (UIInput) component;
 
520
 
 
521
        // Save the old value for use in generating ValueChangedEvents
 
522
        Object oldValue = input.getValue();
 
523
        if (oldValue instanceof String) {
 
524
            try {
 
525
                oldValue = getAsObject(context, component, (String) oldValue);
 
526
            } catch (ConverterException e) {
 
527
                ;
 
528
            }
 
529
        }
 
530
        input.setPrevious(oldValue);
 
531
 
 
532
        // Decode and convert (if needed) the new value
 
533
        String clientId = component.getClientId(context);
 
534
        Map map = context.getExternalContext().getRequestParameterMap();
 
535
        String newString = (String) map.get(clientId);
 
536
        Object newValue = null;
 
537
        try {
 
538
            newValue = getAsObject(context, component, newString);
 
539
            input.setValue(newValue);
 
540
            input.setValid(true);
 
541
        } catch (ConverterException e) {
 
542
            input.setValue(newValue);
 
543
            input.setValid(false);
 
544
            addConverterMessage(context, component, e.getMessage());
 
545
        }
 
546
        
 
547
    }
 
548
    */
 
549
 
 
550
 
 
551
    // --------------------------------------------------------- Package Methods
 
552
 
 
553
 
 
554
    // ------------------------------------------------------- Protected Methods
 
555
 
 
556
 
 
557
    /**
 
558
     * <p>Add an error message denoting a conversion failure.</p>
 
559
     *
 
560
     * @param context The <code>FacesContext</code> for this request
 
561
     * @param component The <code>UIComponent</code> that experienced
 
562
     *  the conversion failure
 
563
     * @param text The text of the error message
 
564
     */
 
565
    /*
 
566
    protected void addConverterMessage(FacesContext context,
 
567
                                       UIComponent component,
 
568
                                       String text) {
 
569
 
 
570
        String clientId = component.getClientId(context);
 
571
        FacesMessage message = new FacesMessage
 
572
            (text,
 
573
             "Conversion error on component '" + clientId + "'");
 
574
        context.addMessage(clientId, message);
 
575
 
 
576
    }
 
577
    */
 
578
 
 
579
 
 
580
    /**
 
581
     * <p>Convert the String representation of this component's value
 
582
     * to the corresponding Object representation.  The default
 
583
     * implementation utilizes the <code>getAsObject()</code> method of any
 
584
     * associated <code>Converter</code>.</p>
 
585
     *
 
586
     * @param context The <code>FacesContext</code> for this request
 
587
     * @param component The <code>UIComponent</code> whose value is
 
588
     *  being converted
 
589
     * @param value The String representation to be converted
 
590
     *
 
591
     * @exception ConverterException if conversion fails
 
592
     */
 
593
    /*
 
594
    protected Object getAsObject(FacesContext context, UIComponent component,
 
595
                                 String value) throws ConverterException {
 
596
 
 
597
        // Identify any Converter associated with this component value
 
598
        ValueBinding vb = component.getValueBinding("value");
 
599
        Converter converter = null;
 
600
        if (component instanceof ValueHolder) {
 
601
            // Acquire explicitly assigned Converter (if any)
 
602
            converter = ((ValueHolder) component).getConverter();
 
603
        }
 
604
        if ((converter == null) && (vb != null)) {
 
605
            Class type = vb.getType(context);
 
606
            if ((type == null) || (type == String.class)) {
 
607
                return (value); // No conversion required for Strings
 
608
            }
 
609
            // Acquire implicit by-type Converter (if any)
 
610
            converter = context.getApplication().createConverter(type);
 
611
        }
 
612
 
 
613
        // Convert the result if we identified a Converter
 
614
        if (converter != null) {
 
615
            return (converter.getAsObject(context, component, value));
 
616
        } else {
 
617
            return (value);
 
618
        }
 
619
 
 
620
    }
 
621
    */
 
622
 
 
623
 
 
624
    /**
 
625
     * <p>Convert the Object representation of this component's value
 
626
     * to the corresponding String representation.  The default implementation
 
627
     * utilizes the <code>getAsString()</code> method of any associated
 
628
     * <code>Converter</code>.</p>
 
629
     *
 
630
     * @param context The <code>FacesContext</code> for this request
 
631
     * @param component The <code>UIComponent</code> whose value is
 
632
     *  being converted
 
633
     * @param value The Object representation to be converted
 
634
     *
 
635
     * @exception ConverterException if conversion fails
 
636
     */
 
637
    protected String getAsString(FacesContext context, UIComponent component,
 
638
                                 Object value) throws ConverterException {
 
639
 
 
640
        // Identify any Converter associated with this component value
 
641
        ValueBinding vb = component.getValueBinding("value");
 
642
        Converter converter = null;
 
643
        if (component instanceof ValueHolder) {
 
644
            // Acquire explicitly assigned Converter (if any)
 
645
            converter = ((ValueHolder) component).getConverter();
 
646
        }
 
647
        if ((converter == null) && (vb != null)) {
 
648
            // Acquire implicit by-type Converter (if any)
 
649
            Class type = vb.getType(context);
 
650
            if (type != null) {
 
651
                converter = context.getApplication().createConverter(type);
 
652
            }
 
653
        }
 
654
 
 
655
        // Convert the result if we identified a Converter
 
656
        if (converter != null) {
 
657
            return (converter.getAsString(context, component, value));
 
658
        } else if (value == null) {
 
659
            return ("");
 
660
        } else if (value instanceof String) {
 
661
            return ((String) value);
 
662
        } else {
 
663
            return (value.toString());
 
664
        }
 
665
 
 
666
    }
 
667
 
 
668
 
 
669
}