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