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 org.rcfaces.core.internal.tools.GridTools;
23  import javax.faces.component.NamingContainer;
24  import javax.faces.model.DataModel;
25  import java.util.HashSet;
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   * @author Olivier Oeuillot
60   */
61  public abstract class CameliaGridComponent extends javax.faces.component.UIComponentBase implements
62  		IRCFacesComponent, IContainerManager, IComponentLifeCycle, ITransientAttributesManager, NamingContainer {
63  	private static final String REVISION = "$Revision: 1.17 $";
64  
65  	private static final Log LOG = LogFactory.getLog(CameliaGridComponent.class);
66  
67  	protected static final Set CAMELIA_ATTRIBUTES=new HashSet(Arrays.asList(new String[] {"value"}));
68  
69  	protected transient IComponentEngine engine;
70  
71  	private transient IStateChildrenList stateChildrenList;
72  
73  	 private transient DataModel dataModel = null;
74  
75  
76  	protected CameliaGridComponent() {
77  		IFactory factory = Constants.getCameliaFactory();
78  
79  		this.engine = factory.createComponentEngine();
80  
81  		IInitializationState state=factory.createInitializationState();
82          initializeComponent(state);	
83      }
84  
85      protected void initializeComponent(IInitializationState state) {
86      	if (Constants.TEMPLATE_ENGINE_SUPPORT) {
87  	        if (isTemplateComponent(state) && state.isConstructionState()) {
88  	        	if (LOG.isDebugEnabled()) {
89  	        		LOG.debug("Call construct template method.");
90  	        	}
91  	            constructTemplate(state);
92  	        }
93  	    }
94  	    if (Constants.COMPONENT_DEFAULT_PROPERTIES_SUPPORT) {
95  	        if (hasDefaultProperties(state) && state.isConstructionState()) {
96  	        	if (LOG.isDebugEnabled()) {
97  	        		LOG.debug("Call setDefaultProperties method.");
98  	        	}
99  	            setDefaultProperties(state);
100 	        }
101 	    }
102 	    
103 	    constructPhase(state.getFacesContext());	    
104     }
105  
106     protected boolean isTemplateComponent(IInitializationState state) {
107         return false;
108     }
109 
110     protected void constructTemplate(IInitializationState state) {
111     }
112 
113     protected boolean hasDefaultProperties(IInitializationState state) {
114         return false;
115     }
116 
117     protected void setDefaultProperties(IInitializationState state) {
118     }
119 
120 	public String getFamily() {
121 		return CameliaComponents.FAMILY;
122 	}
123 
124 	public final String getRendererType() {
125 		String rendererType = super.getRendererType();
126 		if (rendererType == null) {
127         	if (LOG.isTraceEnabled()) {
128         		LOG.trace("RendererType is null for component id='"+getId()+"' class='"+getClass()+"'");
129         	}
130 			return null;
131 		}
132 
133 		if ((this instanceof ILookAndFeelCapability) == false) {
134 			return rendererType;
135 		}
136 
137 		String lookId = ((ILookAndFeelCapability) this).getLookId();
138 		if (lookId == null) {
139 			return rendererType;
140 		}
141 
142 		return rendererType + ":" + lookId;
143 	}
144 
145 	public void restoreState(FacesContext context, Object state) {
146 		if (LOG.isTraceEnabled()) {
147 			LOG.trace("Restoring state of component '"+getId()+"'.");
148 		}
149 		
150 		try {
151 			Object states[] = (Object[]) state;
152 	
153 			super.restoreState(context, states[0]);
154 	
155 			engine.restoreState(context, states[1]);
156 	    	
157 	    } catch (RuntimeException ex) {
158 	    	LOG.error("Can not restore state of component '"+getId()+"'.", ex);
159 	    	
160 	    	throw ex;
161 	    }
162 
163 		if (LOG.isTraceEnabled()) {
164 			LOG.trace("State of component '"+getId()+"' restored.");
165 		}
166 	}
167 
168 	public Object saveState(FacesContext context) {
169 		if (LOG.isTraceEnabled()) {
170 			LOG.trace("Saving state of component '"+getId()+"'.");
171 		}
172 
173 		Object states[] = new Object[2];
174 		try {	
175 			states[0] = super.saveState(context);
176 			states[1] = engine.saveState(context);
177 	    	
178 	    } catch (RuntimeException ex) {
179 	    	LOG.error("Can not save state of component '"+getId()+"'.", ex);
180 	    	
181 	    	throw ex;
182 	    }
183 
184 		if (LOG.isTraceEnabled()) {
185 			LOG.trace("State of component '"+getId()+"' saved.");
186 		}
187 
188 		return states;
189 	}
190 
191 	public void setValueExpression(String name, ValueExpression binding) {
192 		if (getCameliaFields().contains(name)) {
193 			if (name.equals(getCameliaValueAlias())) {
194 				name=Properties.VALUE;
195 			}
196 
197 			if (Properties.VALUE.equals(name)) {
198 				dataModel=null;
199 		}
200 
201 			engine.setProperty(name, binding);
202 			return;
203 		}
204 
205 		if (Properties.VALUE.equals(name)) {
206 				dataModel=null;
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 boolean isRowAvailable() {
629 
630 
631 			return isRowAvailable(null);
632 		
633 	}
634 
635 	public boolean isRowAvailable(FacesContext facesContext) {
636 
637 
638 			return getDataModel(facesContext).isRowAvailable();
639 		
640 	}
641 
642 	public int getRowCount() {
643 
644 
645 				 return getDataModel(null).getRowCount();
646 			
647 	}
648 
649 	public Object getRowData() {
650 
651 
652 				 return getDataModel(null).getRowData();
653 			
654 	}
655 
656 	public DataModel getDataModel(FacesContext facesContext) {
657 
658 
659 				if (dataModel!=null) {
660 					return dataModel;
661 				}
662 				
663 				Object value=getValue(facesContext);
664 				dataModel=GridTools.getDataModel(value, this, facesContext);
665 				
666 				return dataModel;
667 			
668 	}
669 
670 	public DataModel getDataModelValue() {
671 
672 
673 				return getDataModel(null);
674 			
675 	}
676 
677 	public Object getValue() {
678 
679 
680 				return getValue(null);
681 			
682 	}
683 
684 	public Object getValue(FacesContext context) {
685 
686 
687 				return engine.getValue(Properties.VALUE, context);
688 			
689 	}
690 
691 	public void setValue(Object value) {
692 
693 
694 				dataModel=null;
695 				engine.setValue(Properties.VALUE, value);
696 			
697 	}
698 
699 
700 }