View Javadoc

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