View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets;
20  
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import javax.faces.FactoryFinder;
25  
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIViewRoot;
28  import javax.faces.component.UniqueIdVendor;
29  import javax.faces.component.visit.VisitContextFactory;
30  import javax.faces.context.FacesContext;
31  import javax.faces.view.AttachedObjectHandler;
32  import javax.faces.view.EditableValueHolderAttachedObjectHandler;
33  import javax.faces.view.facelets.FaceletContext;
34  
35  /**
36   * @since 2.0.1
37   * @author Leonardo Uribe (latest modification by $Author$)
38   * @version $Revision$ $Date$
39   */
40  abstract public class FaceletCompositionContext
41  {
42      static protected final String FACELET_COMPOSITION_CONTEXT_KEY = "oam.facelets.FACELET_COMPOSITION_CONTEXT";
43  
44      protected FaceletCompositionContext()
45      {
46      }
47      
48      static public FaceletCompositionContext getCurrentInstance()
49      {
50          return (FaceletCompositionContext)
51                  FacesContext.getCurrentInstance().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
52      }
53      
54      static public FaceletCompositionContext getCurrentInstance(FaceletContext ctx)
55      {
56          if (ctx instanceof AbstractFaceletContext)
57          {
58              return ((AbstractFaceletContext)ctx).getFaceletCompositionContext();
59          }
60          else
61          {
62              // Here we have two choices: retrieve it throught ThreadLocal var
63              // or use the attribute value on FacesContext, but it seems better
64              // use the FacesContext attribute map.
65              return (FaceletCompositionContext)
66                      ctx.getFacesContext().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
67          }
68      }
69      
70      static public FaceletCompositionContext getCurrentInstance(FacesContext ctx)
71      {
72          return (FaceletCompositionContext) ctx.getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
73      }
74  
75      public void init(FacesContext facesContext)
76      {
77          facesContext.getAttributes().put(
78                  FaceletCompositionContext.FACELET_COMPOSITION_CONTEXT_KEY, this);
79      }
80  
81      /**
82       * Releases the MyFaceletContext object.  This method must only
83       * be called by the code that created the MyFaceletContext.
84       */
85      public void release(FacesContext facesContext)
86      {
87          facesContext.getAttributes().remove(FACELET_COMPOSITION_CONTEXT_KEY);
88      }
89      
90      public abstract FaceletFactory getFaceletFactory();
91      
92      /**
93       * Return the composite component being applied on the current facelet. 
94       * 
95       * Note this is different to UIComponent.getCurrentCompositeComponent, because a composite
96       * component is added to the stack each time a composite:implementation tag handler is applied.
97       * 
98       * This could be used by InsertChildrenHandler and InsertFacetHandler to retrieve the current
99       * composite component to be applied.
100      * 
101      * @since 2.0.1
102      * @return
103      */
104     public abstract UIComponent getCompositeComponentFromStack();
105 
106     /**
107      * @since 2.0.1
108      * @param parent
109      */
110     public abstract void pushCompositeComponentToStack(UIComponent parent);
111 
112     /**
113      * @since 2.0.1
114      */
115     public abstract void popCompositeComponentToStack();
116     
117     /**
118      * Return the latest UniqueIdVendor created from stack. The reason why we need to keep
119      * a UniqueIdVendor stack is because we need to look the closest one in ComponentTagHandlerDelegate.
120      * Note that facelets tree is built from leafs to root, that means use UIComponent.getParent() does not
121      * always return parent components.
122      * 
123      * @since 2.0.1
124      * @return
125      */
126     public abstract UniqueIdVendor getUniqueIdVendorFromStack();
127 
128     /**
129      * @since 2.0.1
130      * @param parent
131      */
132     public abstract void pushUniqueIdVendorToStack(UniqueIdVendor parent);
133 
134     /**
135      * @since 2.0.1
136      */
137     public abstract void popUniqueIdVendorToStack();
138     
139     /**
140      * Gets the top of the validationGroups stack.
141      * @return
142      * @since 2.0.1
143      */
144     @Deprecated
145     public abstract String getFirstValidationGroupFromStack();
146     
147     /**
148      * Removes top of stack.
149      * @since 2.0.1
150      */
151     @Deprecated
152     public abstract void popValidationGroupsToStack();
153     
154     /**
155      * Pushes validationGroups to the stack.
156      * @param validationGroups
157      * @since 2.0.1
158      */
159     @Deprecated
160     public abstract void pushValidationGroupsToStack(String validationGroups);
161     
162     /**
163      * Gets all validationIds on the stack.
164      * @return
165      * @since 2.0.1
166      */
167     @Deprecated
168     public abstract Iterator<String> getExcludedValidatorIds();
169     
170     /**
171      * Removes top of stack.
172      * @since 2.0.1
173      */
174     @Deprecated
175     public abstract void popExcludedValidatorIdToStack();
176     
177     /**
178      * Pushes validatorId to the stack of excluded validatorIds.
179      * @param validatorId
180      * @since 2.0.1
181      */
182     @Deprecated
183     public abstract void pushExcludedValidatorIdToStack(String validatorId);
184     
185     /**
186      * Gets all validationIds on the stack.
187      * @return
188      * @since 2.0.1
189      */
190     @Deprecated
191     public abstract Iterator<String> getEnclosingValidatorIds();
192     
193     /**
194      * Removes top of stack.
195      * @since 2.0.1
196      */
197     public abstract void popEnclosingValidatorIdToStack();
198     
199     /**
200      * Pushes validatorId to the stack of all enclosing validatorIds.
201      * @param validatorId
202      * @since 2.0.1
203      */
204     @Deprecated
205     public abstract void pushEnclosingValidatorIdToStack(String validatorId);
206     
207     /**
208      * Pushes validatorId to the stack of all enclosing validatorIds.
209      * 
210      * @param validatorId
211      * @param attachedObjectHandler
212      * @since 2.0.10
213      */
214     public abstract void pushEnclosingValidatorIdToStack(String validatorId, 
215             EditableValueHolderAttachedObjectHandler attachedObjectHandler);
216 
217     /**
218      * Gets all validationIds with its associated EditableValueHolderAttachedObjectHandler from the stack.
219      * 
220      * @return
221      * @since 2.0.10
222      */
223     public abstract Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>> 
224         getEnclosingValidatorIdsAndHandlers();
225     
226     /**
227      * 
228      * @param id
229      * @return
230      * @since 2.0.10
231      */
232     public abstract boolean containsEnclosingValidatorId(String id);
233     
234     /**
235      * Check if this build is being refreshed, adding transient components
236      * and adding/removing components under c:if or c:forEach or not.
237      * 
238      * @return
239      * @since 2.0.1
240      */
241     public abstract boolean isRefreshingTransientBuild();
242     
243     /**
244      * Check if this build should be marked as initial state. In other words,
245      * all components must call UIComponent.markInitialState.
246      * 
247      * @return
248      * @since 2.0.1
249      */
250     public abstract boolean isMarkInitialState();
251     
252     public void setMarkInitialState(boolean value)
253     {
254     }
255     
256     /**
257      * Check if the current view will be refreshed with partial state saving.
258      * 
259      * This param is used in two posible events:
260      * 
261      * 1. To notify UIInstruction instances to look for instances moved by
262      *    cc:insertChildren or cc:insertFacet.
263      * 2. To do proper actions when a tag that could change tree structure is applied
264      *    (c:if, c:forEach...)
265      * 
266      * @return
267      * @since 2.0.1
268      */
269     public abstract boolean isRefreshTransientBuildOnPSS();
270     
271     /**
272      * 
273      * @since 2.0.12, 2.1.6
274      * @return
275      */
276     public boolean isRefreshTransientBuildOnPSSPreserveState()
277     {
278         return false;
279     }
280     
281     /**
282      * Check if we are using partial state saving on this view
283      * 
284      * @return
285      * @since 2.0.1
286      */
287     public abstract boolean isUsingPSSOnThisView();
288     
289     /**
290      * @since 2.0.1
291      * @return
292      */
293     public abstract boolean isMarkInitialStateAndIsRefreshTransientBuildOnPSS();
294 
295     /**
296      * Add to the composite component parent this handler, so it will be processed later when
297      * ViewDeclarationLanguage.retargetAttachedObjects is called.
298      *
299      * Tag Handlers exposing attached objects should call this method to expose them when the
300      * parent to be applied is a composite components.
301      *
302      * @since 2.0.2
303      * @param compositeComponentParent
304      * @param handler
305      */
306     public abstract void addAttachedObjectHandler(UIComponent compositeComponentParent, AttachedObjectHandler handler);
307 
308     /**
309      * Remove from the composite component parent the list of attached handlers.
310      * 
311      * @since 2.0.2
312      * @param compositeComponentParent
313      */
314     public abstract void removeAttachedObjectHandlers(UIComponent compositeComponentParent);
315 
316     /**
317      * Retrieve the list of object handlers attached to a composite component parent. 
318      * 
319      * @since 2.0.2
320      * @param compositeComponentParent
321      */
322     public abstract List<AttachedObjectHandler> getAttachedObjectHandlers(UIComponent compositeComponentParent);
323 
324     /**
325      * Marks all direct children and Facets with an attribute for deletion.
326      *
327      * @since 2.0.2
328      * @see #finalizeForDeletion(UIComponent)
329      * @param component
330      *            UIComponent to mark
331      */
332     public abstract void markForDeletion(UIComponent component);
333     
334     /**
335      * Used in conjunction with markForDeletion where any UIComponent marked will be removed.
336      * 
337      * @since 2.0.2
338      * @param component
339      *            UIComponent to finalize
340      */
341     public abstract void finalizeForDeletion(UIComponent component);
342     
343     public void removeComponentForDeletion(UIComponent component)
344     {
345     }
346 
347     /**
348      * Marks the given resource for deletion. Is to be used for relocatable 
349      * components instead of {@link #markForDeletion(UIComponent)}.
350      *
351      * @since 2.0.17 2.1.11
352      * @param component
353      *            UIComponent to finalize
354      */
355     public void markRelocatableResourceForDeletion(UIComponent component)
356     {
357     }
358 
359     /**
360      * Used to clean up all unused relocatable components on the root component.
361      *
362      * @since 2.0.17 2.1.11
363      * @param root
364      *            UIComponent to finalize (root component)
365      */
366     public void finalizeRelocatableResourcesForDeletion(UIViewRoot root)
367     {
368     }
369 
370     /**
371      * Add a method expression as targeted for the provided composite component
372      * 
373      * @since 2.0.3
374      * @param targetedComponent
375      * @param attributeName
376      * @param backingValue A value that could be useful to revert its effects.
377      */
378     public abstract void addMethodExpressionTargeted(UIComponent targetedComponent, String attributeName,
379                                                      Object backingValue);
380 
381     /**
382      * Check if the MethodExpression attribute has been applied using vdl.retargetMethodExpression 
383      * 
384      * @since 2.0.3
385      * @param compositeComponentParent
386      * @param attributeName
387      * @return
388      */
389     public abstract boolean isMethodExpressionAttributeApplied(UIComponent compositeComponentParent,
390                                                                String attributeName);
391     
392     /**
393      * Mark the MethodExpression attribute as applied using vdl.retargetMethodExpression
394      * 
395      * @since 2.0.3
396      * @param compositeComponentParent
397      * @param attributeName
398      */
399     public abstract void markMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
400     
401     /**
402      * Clear the MethodExpression attribute to call vdl.retargetMethodExpression again
403      * 
404      * @since 2.0.3
405      * @param compositeComponentParent
406      * @param attributeName
407      */
408     public abstract void clearMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
409     
410     /**
411      * Remove a method expression as targeted for the provided composite component
412      * 
413      * @since 2.0.3
414      * @param targetedComponent
415      * @param attributeName
416      * @return A value that could be useful to revert its effects.
417      */
418     public abstract Object removeMethodExpressionTargeted(UIComponent targetedComponent, String attributeName);
419     
420     /**
421      * Indicates if a EL Expression can be or not cached by facelets vdl.
422      * 
423      * @since 2.0.8
424      * @return
425      */
426     public ELExpressionCacheMode getELExpressionCacheMode()
427     {
428         return ELExpressionCacheMode.noCache;
429     }
430     
431     /**
432      * 
433      * @since 2.0.9
434      * @return
435      */
436     public boolean isWrapTagExceptionsAsContextAware()
437     {
438         return true;
439     }
440 
441     /**
442      * Start a new unique id section, which means a new counter is used to
443      * generate unique ids to components
444      * 
445      * @since 2.0.10, 2.1.4
446      * @return
447      */
448     public String startComponentUniqueIdSection()
449     {
450         return null;
451     }
452     
453     /**
454      * Start a new unique id section, which means a new counter is used to
455      * generate unique ids to components, but appending a base to the
456      * new counter.
457      * 
458      * @since 2.2.0
459      * @return
460      */
461     public String startComponentUniqueIdSection(String base)
462     {
463         return null;
464     }
465     
466     /**
467      * @since 2.2.0
468      * @param base 
469      */
470     public void endComponentUniqueIdSection(String base)
471     {
472     }
473     
474     /**
475      * Generate a unique id that will be used later to derive a unique id per tag
476      * by FaceletContext.generateUniqueId(). This generator ensures uniqueness per
477      * view but FaceletContext.generateUniqueId() ensures uniqueness per view and
478      * per facelet hierarchy, so different included facelets will generate different
479      * ids.
480      * 
481      * @return
482      */
483     public String generateUniqueId()
484     {
485         return null;
486     }
487     
488     public void generateUniqueId(StringBuilder builderToAdd)
489     {
490     }
491     
492     /**
493      * Generate a unique id for component instances. 
494      * 
495      * @return
496      */
497     public String generateUniqueComponentId()
498     {
499         return null;
500     }
501 
502     /**
503      * Ends the current unique id section, so the previous counter will be used
504      * to generate unique ids to components.
505      */
506     public void endComponentUniqueIdSection()
507     {
508     }
509     
510     /**
511      * Set the iterator used to retrieve unique ids.
512      * 
513      * since 2.1.7, 2.0.13
514      * @param uniqueIdsIterator 
515      */
516     public void setUniqueIdsIterator(Iterator<String> uniqueIdsIterator)
517     {
518     }
519     
520     /**
521      * Activater record unique id mode, so an structure will be
522      * used to hold those values.
523      * 
524      * since 2.1.7, 2.0.13
525      */
526     public void initUniqueIdRecording()
527     {
528     }
529     
530     /**
531      * Add an unique id to the list if recording is enabled,
532      * if recording is not enabled it has no effect.
533      * 
534      * since 2.1.7, 2.0.13
535      * @param uniqueId 
536      */
537     public void addUniqueId(String uniqueId)
538     {
539     }
540     
541     /**
542      * Return the unique id from the iterator if applies
543      * 
544      * since 2.1.7, 2.0.13
545      * @return 
546      */
547     public String getUniqueIdFromIterator()
548     {
549         return null;
550     }
551     
552     /**
553      * Return the list of unique ids
554      * 
555      * since 2.1.7, 2.0.13
556      * @return 
557      */
558     public List<String> getUniqueIdList()
559     {
560         return null;
561     }
562 
563     /**
564      * Increment the unique id without construct it.
565      * 
566      * since 2.1.7, 2.0.13
567      */
568     public void incrementUniqueId()
569     {
570     }
571 
572     /**
573      * Check if the facelet is building view metadata
574      * 
575      * since 2.1.7, 2.0.13
576      * @return 
577      */
578     public boolean isBuildingViewMetadata()
579     {
580         return FaceletViewDeclarationLanguage.isBuildingViewMetadata(
581                 FacesContext.getCurrentInstance());
582     }
583     
584     /**
585      * Call this method to indicate a f:metadata section is about to be processed
586      * 
587      * since 2.1.7, 2.0.13
588      */
589     public void startMetadataSection()
590     {
591     }
592     
593     /**
594      * Call this method to indicate f:metadata section has been already processed
595      * 
596      * since 2.1.7, 2.0.13
597      */
598     public void endMetadataSection()
599     {
600     }
601     
602     /**
603      * Check if the component is created inside f:metadata section
604      * 
605      * since 2.1.7, 2.0.13
606      * @return 
607      */
608     public boolean isInMetadataSection()
609     {
610        return false;
611     }
612     
613     /**
614      * Check if the section to be processed is being refreshed.
615      * 
616      * since 2.1.7, 2.0.13
617      * @return 
618      */
619     public boolean isRefreshingSection()
620     {
621        return isRefreshingTransientBuild() ||  (!isBuildingViewMetadata() && isInMetadataSection());
622     }
623 
624     /**
625      * 
626      * @since 2.1.8, 2.0.14
627      */
628     public void incrementUniqueComponentId()
629     {
630     }
631     
632     public StringBuilder getSharedStringBuilder()
633     {
634         return new StringBuilder();
635     }
636 
637     /**
638      * Returns the current nesting level of composite components found. If
639      * no composite component has been used returns 0.
640      * 
641      * @since 2.1.9, 2.0.15
642      */
643     public int getCompositeComponentLevel()
644     {
645         return 0;
646     }
647     
648     public boolean isDynamicCompositeComponentHandler()
649     {
650         return false;
651     }
652     
653     public void setDynamicCompositeComponentHandler(boolean value)
654     {
655     }
656     
657     public void pushDynamicComponentSection(String baseKey)
658     {
659     }
660     
661     public void popDynamicComponentSection()
662     {
663     }
664     
665     /**
666      * Check if the algorithm is applying a dynamic component and the current component
667      * is the top level one. This is necessary to avoid remove/add the component under
668      * a refresh and in that way change the position of the component in the tree. Remember
669      * facelets algorithm removes/add components to sort the components under a refresh, but
670      * in this case, it is up to the user to put the component in the tree, so the idea is
671      * do not make interference with the user's code. Note if the dynamic content is wrapped
672      * by a generated panel, the top level component is the wrapper itself, which has no 
673      * attached tag handler.
674      * 
675      * @since 2.2
676      * @return 
677      */
678     public boolean isDynamicComponentTopLevel()
679     {
680         return false;
681     }
682     
683     public void setDynamicComponentTopLevel(boolean value)
684     {
685     }
686     
687     /**
688      * Indicate if the current facelet section is a dynamic component section,
689      * which means it was added to the component tree using vdl.createComponent(...);
690      * 
691      * @since 2.2
692      * @return 
693      */
694     public boolean isDynamicComponentSection()
695     {
696         return false;
697     }
698     
699     public UIViewRoot getViewRoot(FacesContext facesContext)
700     {
701         return facesContext.getViewRoot();
702     }
703     
704     public void setViewRoot(UIViewRoot root)
705     {
706     }
707     
708     public VisitContextFactory getVisitContextFactory()
709     {
710         return (VisitContextFactory)FactoryFinder.getFactory(FactoryFinder.VISIT_CONTEXT_FACTORY);
711     }
712 }