1
2
3 package org.rcfaces.core.internal.component;
4
5 import java.util.List;
6 import java.util.Collections;
7 import java.util.Set;
8 import java.io.IOException;
9
10 import javax.el.ValueExpression;
11
12 import javax.faces.context.FacesContext;
13 import javax.faces.render.Renderer;
14 import javax.faces.event.ActionEvent;
15 import javax.faces.event.FacesEvent;
16 import javax.faces.event.FacesListener;
17 import javax.faces.event.PhaseId;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import javax.faces.convert.Converter;
23 import org.rcfaces.core.internal.capability.IConvertValueHolder;
24 import java.util.HashSet;
25 import java.lang.String;
26 import java.util.Arrays;
27
28
29 import org.rcfaces.core.component.capability.IAsyncDecodeModeCapability;
30 import org.rcfaces.core.component.capability.IHiddenModeCapability;
31 import org.rcfaces.core.component.capability.IImmediateCapability;
32 import org.rcfaces.core.component.capability.ILookAndFeelCapability;
33 import org.rcfaces.core.component.capability.IValidationEventCapability;
34 import org.rcfaces.core.component.capability.IVisibilityCapability;
35 import org.rcfaces.core.internal.Constants;
36 import org.rcfaces.core.internal.RcfacesContext;
37
38 import org.rcfaces.core.internal.capability.IVariableScopeCapability;
39 import org.rcfaces.core.internal.capability.IComponentEngine;
40 import org.rcfaces.core.internal.capability.IComponentLifeCycle;
41 import org.rcfaces.core.internal.capability.IListenerStrategy;
42 import org.rcfaces.core.internal.capability.IRCFacesComponent;
43 import org.rcfaces.core.internal.capability.IStateChildrenList;
44 import org.rcfaces.core.internal.component.CameliaComponents;
45 import org.rcfaces.core.internal.component.RestoreViewPhaseListener;
46 import org.rcfaces.core.internal.component.IFactory;
47 import org.rcfaces.core.internal.component.IInitializationState;
48 import org.rcfaces.core.internal.converter.StrategyListenerConverter;
49 import org.rcfaces.core.internal.manager.IContainerManager;
50 import org.rcfaces.core.internal.manager.ITransientAttributesManager;
51 import org.rcfaces.core.internal.renderkit.IAsyncRenderer;
52 import org.rcfaces.core.internal.renderkit.IRendererExtension;
53 import org.rcfaces.core.internal.tools.ComponentTools;
54 import org.rcfaces.core.internal.tools.BindingTools;
55 import org.rcfaces.core.event.IValidationListener;
56 import org.rcfaces.core.event.ValidationEvent;
57
58
59
60
61 public abstract class CameliaOutputComponent extends javax.faces.component.UIOutput implements
62 IRCFacesComponent, IContainerManager, IComponentLifeCycle, ITransientAttributesManager, IConvertValueHolder {
63 private static final String REVISION = "$Revision: 1.17 $";
64
65 private static final Log LOG = LogFactory.getLog(CameliaOutputComponent.class);
66
67 protected static final Set CAMELIA_ATTRIBUTES=new HashSet(Arrays.asList(new String[] {"converter","value"}));
68
69 protected transient IComponentEngine engine;
70
71 private transient IStateChildrenList stateChildrenList;
72
73
74 protected CameliaOutputComponent() {
75 IFactory factory = Constants.getCameliaFactory();
76
77 this.engine = factory.createComponentEngine();
78
79 IInitializationState state=factory.createInitializationState();
80 initializeComponent(state);
81 }
82
83 protected void initializeComponent(IInitializationState state) {
84 if (Constants.TEMPLATE_ENGINE_SUPPORT) {
85 if (isTemplateComponent(state) && state.isConstructionState()) {
86 if (LOG.isDebugEnabled()) {
87 LOG.debug("Call construct template method.");
88 }
89 constructTemplate(state);
90 }
91 }
92 if (Constants.COMPONENT_DEFAULT_PROPERTIES_SUPPORT) {
93 if (hasDefaultProperties(state) && state.isConstructionState()) {
94 if (LOG.isDebugEnabled()) {
95 LOG.debug("Call setDefaultProperties method.");
96 }
97 setDefaultProperties(state);
98 }
99 }
100
101 constructPhase(state.getFacesContext());
102 }
103
104 protected boolean isTemplateComponent(IInitializationState state) {
105 return false;
106 }
107
108 protected void constructTemplate(IInitializationState state) {
109 }
110
111 protected boolean hasDefaultProperties(IInitializationState state) {
112 return false;
113 }
114
115 protected void setDefaultProperties(IInitializationState state) {
116 }
117
118 public String getFamily() {
119 return CameliaComponents.FAMILY;
120 }
121
122 public final String getRendererType() {
123 String rendererType = super.getRendererType();
124 if (rendererType == null) {
125 if (LOG.isTraceEnabled()) {
126 LOG.trace("RendererType is null for component id='"+getId()+"' class='"+getClass()+"'");
127 }
128 return null;
129 }
130
131 if ((this instanceof ILookAndFeelCapability) == false) {
132 return rendererType;
133 }
134
135 String lookId = ((ILookAndFeelCapability) this).getLookId();
136 if (lookId == null) {
137 return rendererType;
138 }
139
140 return rendererType + ":" + lookId;
141 }
142
143 public void restoreState(FacesContext context, Object state) {
144 if (LOG.isTraceEnabled()) {
145 LOG.trace("Restoring state of component '"+getId()+"'.");
146 }
147
148 try {
149 Object states[] = (Object[]) state;
150
151 super.restoreState(context, states[0]);
152
153 engine.restoreState(context, states[1]);
154
155 } catch (RuntimeException ex) {
156 LOG.error("Can not restore state of component '"+getId()+"'.", ex);
157
158 throw ex;
159 }
160
161 if (LOG.isTraceEnabled()) {
162 LOG.trace("State of component '"+getId()+"' restored.");
163 }
164 }
165
166 public Object saveState(FacesContext context) {
167 if (LOG.isTraceEnabled()) {
168 LOG.trace("Saving state of component '"+getId()+"'.");
169 }
170
171 Object states[] = new Object[2];
172 try {
173 states[0] = super.saveState(context);
174 states[1] = engine.saveState(context);
175
176 } catch (RuntimeException ex) {
177 LOG.error("Can not save state of component '"+getId()+"'.", ex);
178
179 throw ex;
180 }
181
182 if (LOG.isTraceEnabled()) {
183 LOG.trace("State of component '"+getId()+"' saved.");
184 }
185
186 return states;
187 }
188
189 public void setValueExpression(String name, ValueExpression binding) {
190 if (getCameliaFields().contains(name)) {
191 if (name.equals(getCameliaValueAlias())) {
192 name=Properties.VALUE;
193 }
194
195
196
197 engine.setProperty(name, binding);
198 return;
199 }
200
201
202
203 super.setValueExpression(name, binding);
204 }
205
206 protected Set getCameliaFields() {
207 return CAMELIA_ATTRIBUTES;
208 }
209
210 protected String getCameliaValueAlias() {
211 return null;
212 }
213
214 public final ValueExpression getValueExpression(String name) {
215 if (getCameliaFields().contains(name)) {
216 if (name.equals(getCameliaValueAlias())) {
217 name=Properties.VALUE;
218 }
219
220 return engine.getValueExpressionProperty(name);
221 }
222
223 return super.getValueExpression(name);
224 }
225
226
227
228
229
230
231
232
233
234 public void encodeBegin(FacesContext context) throws IOException {
235 if (context == null) {
236 throw new NullPointerException("FacesContext is null");
237 }
238
239 try {
240 super.encodeBegin(context);
241
242 } catch (RuntimeException ex) {
243 LOG.error("Can not encode-begin component '"+getId()+"'.", ex);
244
245 throw ex;
246 }
247 }
248
249 public void encodeChildren(FacesContext context) throws IOException {
250 if (context == null) {
251 throw new NullPointerException("FacesContext is null");
252 }
253
254 try {
255 super.encodeChildren(context);
256
257 } catch (RuntimeException ex) {
258 LOG.error("Can not encode children of component '"+getId()+"'.", ex);
259
260 throw ex;
261 }
262 }
263
264 public void encodeEnd(FacesContext context) throws IOException {
265 if (context == null) {
266 throw new NullPointerException("FacesContext is null");
267 }
268
269 try {
270 super.encodeEnd(context);
271
272 } catch (RuntimeException ex) {
273 LOG.error("Can not encode-end component '"+getId()+"'.", ex);
274
275 throw ex;
276 }
277 }
278
279 protected boolean verifyAsyncDecode(FacesContext context, PhaseId phaseId) {
280 return ComponentTools.verifyAsyncDecode(context, (IAsyncDecodeModeCapability) this, phaseId);
281 }
282
283 public void processDecodes(FacesContext context) {
284 if (context == null) {
285 throw new NullPointerException();
286 }
287
288 try {
289 if (isRendered()==false) {
290 return;
291 }
292
293 if (this instanceof IAsyncDecodeModeCapability) {
294 if (verifyAsyncDecode(context, PhaseId.APPLY_REQUEST_VALUES)==false) {
295 return;
296 }
297 }
298
299 ComponentTools.IVarScope varScope = null;
300 if (this instanceof IVariableScopeCapability) {
301 varScope=BindingTools.processVariableScope(context, (IVariableScopeCapability)this, PhaseId.APPLY_REQUEST_VALUES);
302 }
303
304 engine.startDecodes(context);
305
306 Renderer renderer = getRenderer(context);
307 if ((renderer instanceof IRendererExtension) == false) {
308 super.processDecodes(context);
309
310 } else {
311 CameliaComponents.processDecodes(context, this, renderer);
312 }
313
314 boolean immediate=false;
315 if (this instanceof IValidationEventCapability) {
316 if (this instanceof IImmediateCapability) {
317 immediate=((IImmediateCapability)this).isImmediate();
318 }
319 }
320
321 if (immediate) {
322 if (ComponentTools.hasValidationServerListeners(getFacesListeners(IValidationListener.class))) {
323 this.broadcast(new ValidationEvent(this));
324 }
325 processEngineValidators(context);
326 }
327
328 if (varScope!=null) {
329 varScope.popVar(context);
330 }
331
332 } catch (RuntimeException ex) {
333 LOG.error("Can not decode component '"+getId()+"'.", ex);
334
335 throw ex;
336 }
337 }
338
339 public void processValidators(FacesContext context) {
340 if (context == null) {
341 throw new NullPointerException("Context is NULL to processValidators");
342 }
343
344 try {
345
346 if (isRendered()==false) {
347 return;
348 }
349
350 if (this instanceof IAsyncDecodeModeCapability) {
351 if (verifyAsyncDecode(context, PhaseId.PROCESS_VALIDATIONS)==false) {
352 return;
353 }
354 }
355
356 ComponentTools.IVarScope varScope = null;
357 if (this instanceof IVariableScopeCapability) {
358 varScope=BindingTools.processVariableScope(context, (IVariableScopeCapability)this, PhaseId.PROCESS_VALIDATIONS);
359 }
360
361 super.processValidators(context);
362
363 boolean immediate=false;
364 if (this instanceof IValidationEventCapability) {
365 if (this instanceof IImmediateCapability) {
366 immediate=((IImmediateCapability)this).isImmediate();
367 }
368 }
369
370 if (immediate==false) {
371 if (ComponentTools.hasValidationServerListeners(getFacesListeners(IValidationListener.class))) {
372 this.broadcast(new ValidationEvent(this));
373 }
374
375 processEngineValidators(context);
376 }
377
378 if (varScope!=null) {
379 varScope.popVar(context);
380 }
381
382 } catch (RuntimeException ex) {
383 LOG.error("Can not valid component '"+getId()+"'.", ex);
384
385 throw ex;
386 }
387 }
388
389 protected void processEngineValidators(FacesContext context) {
390 engine.processValidation(context);
391 }
392
393 public void processUpdates(FacesContext context) {
394
395 try {
396
397 if (isRendered()==false) {
398 return;
399 }
400
401 if (this instanceof IAsyncDecodeModeCapability) {
402 if (verifyAsyncDecode(context, PhaseId.UPDATE_MODEL_VALUES)==false) {
403 return;
404 }
405 }
406
407 ComponentTools.IVarScope varScope = null;
408 if (this instanceof IVariableScopeCapability) {
409 varScope=BindingTools.processVariableScope(context, (IVariableScopeCapability)this, PhaseId.UPDATE_MODEL_VALUES);
410 }
411
412 processEngineUpdates(context);
413
414 super.processUpdates(context);
415
416 if (varScope!=null) {
417 varScope.popVar(context);
418 }
419
420 } catch (RuntimeException ex) {
421 LOG.error("Can not update component '"+getId()+"'.", ex);
422
423 throw ex;
424 }
425 }
426
427 protected void processEngineUpdates(FacesContext context) {
428 engine.processUpdates(context);
429 }
430
431
432
433
434
435
436 public final List getChildren() {
437 if (Constants.STATED_COMPONENT_CHILDREN_LIST==false) {
438 return super.getChildren();
439 }
440
441 List list = super.getChildren();
442
443 if (stateChildrenList == null) {
444 stateChildrenList = engine.createStateChildrenList();
445 }
446
447 stateChildrenList.setChildren(list);
448
449 return stateChildrenList;
450 }
451
452 public final int getChildrenListState() {
453 if (Constants.STATED_COMPONENT_CHILDREN_LIST==false) {
454 throw new UnsupportedOperationException("STATED_COMPONENT_CHILDREN_LIST=false");
455 }
456
457 if (stateChildrenList == null) {
458 return 0;
459 }
460
461 return stateChildrenList.getState();
462 }
463
464 public final Object getTransientAttribute(String name) {
465 return engine.getTransientAttribute(name);
466 }
467
468 public final Object setTransientAttribute(String name, Object value) {
469 return engine.setTransientAttribute(name, value);
470 }
471
472 public final boolean isClientRendered() {
473 if ((this instanceof IVisibilityCapability)==false) {
474 return true;
475 }
476
477 IVisibilityCapability visibilityCapability=(IVisibilityCapability)this;
478
479 Boolean visible=visibilityCapability.getVisibleState();
480 if (visible==null || visible.booleanValue()) {
481 return true;
482 }
483
484 if ((this instanceof IHiddenModeCapability)==false) {
485 return false;
486 }
487
488 IHiddenModeCapability hiddenModeCapability=(IHiddenModeCapability)this;
489
490 int hiddenMode=hiddenModeCapability.getHiddenMode();
491 if (IHiddenModeCapability.SERVER_HIDDEN_MODE==hiddenMode) {
492 return false;
493 }
494
495 return true;
496 }
497
498 public boolean isRendered() {
499 if (super.isRendered()==false) {
500 return false;
501 }
502
503 return isClientRendered();
504 }
505
506 public void setRendered(ValueExpression binding) {
507 setValueExpression("rendered", binding);
508 }
509
510
511 public final IAsyncRenderer getAsyncRenderer(FacesContext facesContext) {
512 Renderer renderer=getRenderer(facesContext);
513 if (renderer instanceof IAsyncRenderer) {
514 return (IAsyncRenderer) renderer;
515 }
516
517 return null;
518 }
519
520 public void queueEvent(FacesEvent e) {
521
522
523 if ((e instanceof ActionEvent) && e.getComponent()==this) {
524 if (this instanceof IImmediateCapability) {
525 IImmediateCapability immediateCapability=(IImmediateCapability)this;
526
527 if (immediateCapability.isImmediate()) {
528 e.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
529
530 } else {
531 e.setPhaseId(PhaseId.INVOKE_APPLICATION);
532 }
533 }
534 }
535
536 super.queueEvent(e);
537 }
538
539 public void clearListeners() {
540 FacesListener fcs[]=getFacesListeners(FacesListener.class);
541 for(int i=0;i<fcs.length;i++) {
542 removeFacesListener(fcs[i]);
543 }
544 }
545
546 public void constructPhase(FacesContext facesContext) {
547 }
548
549 public void initializePhase(FacesContext facesContext, boolean reused) {
550 if (reused) {
551
552 RcfacesContext rcfacesContext = RcfacesContext
553 .getInstance(facesContext);
554 int faceletListenerMode = rcfacesContext
555 .getListenerManagerStrategy();
556
557 if ((IListenerStrategy.CLEAN_ALL & faceletListenerMode) > 0) {
558 clearListeners();
559 }
560 }
561 }
562
563 public void decodePhase(FacesContext facesContext) {
564 }
565
566 public void validationPhase(FacesContext facesContext) {
567 }
568
569 public void updatePhase(FacesContext facesContext) {
570 }
571
572 public void renderPhase(FacesContext facesContext) {
573 }
574
575 public boolean confirmListenerAppend(FacesContext facesContext, Class facesListenerClass){
576
577 RcfacesContext rcfacesContext = RcfacesContext
578 .getInstance(facesContext);
579 int faceletListenerMode = rcfacesContext.getListenerManagerStrategy();
580
581 if (((IListenerStrategy.ADD_IF_NEW | IListenerStrategy.CLEAN_BY_CLASS) & faceletListenerMode) == 0) {
582 return true;
583 }
584
585 FacesListener fcs[] = getFacesListeners(facesListenerClass);
586 if ((IListenerStrategy.ADD_IF_NEW & faceletListenerMode) > 0) {
587 return fcs.length == 0;
588 }
589
590 if ((IListenerStrategy.CLEAN_BY_CLASS & faceletListenerMode) > 0) {
591 for (int i = 0; i < fcs.length; i++) {
592 removeFacesListener(fcs[i]);
593 }
594
595 return true;
596 }
597
598 return true;
599 }
600
601 public String toString() {
602 String name=getClass().getName();
603 name=name.substring(name.lastIndexOf('.')+1);
604
605 String s=name+"[id='"+getId()+"'";
606
607 if (isRendered()==false) {
608 s+=",rendered=false";
609 }
610
611 s+=","+engine.toString();
612
613 s+=",rendererId='"+getRendererType()+"'";
614
615 if (getFamily()!=CameliaComponents.FAMILY) {
616 s+=",family='"+getFamily()+"'";
617 }
618
619 return s+"]";
620 }
621
622 public void setConverter(String converterId) {
623
624
625 setConverter(null, converterId);
626
627 }
628
629 public void setConverter(FacesContext facesContext, String converterId) {
630
631
632 if (facesContext==null) {
633 facesContext=FacesContext.getCurrentInstance();
634 }
635 Converter converter = facesContext.getApplication().createConverter(converterId);
636 this.setConverter(converter);
637
638 }
639
640
641 }