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
25 import javax.faces.component.UIComponent;
26 import javax.faces.component.UniqueIdVendor;
27 import javax.faces.context.FacesContext;
28 import javax.faces.view.AttachedObjectHandler;
29 import javax.faces.view.EditableValueHolderAttachedObjectHandler;
30 import javax.faces.view.facelets.FaceletContext;
31
32 /**
33 * @since 2.0.1
34 * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
35 * @version $Revision: 1306710 $ $Date: 2012-03-28 23:27:03 -0500 (Wed, 28 Mar 2012) $
36 */
37 abstract public class FaceletCompositionContext
38 {
39 static protected final String FACELET_COMPOSITION_CONTEXT_KEY = "oam.facelets.FACELET_COMPOSITION_CONTEXT";
40
41 protected FaceletCompositionContext()
42 {
43 }
44
45 static public FaceletCompositionContext getCurrentInstance()
46 {
47 return (FaceletCompositionContext)
48 FacesContext.getCurrentInstance().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
49 }
50
51 static public FaceletCompositionContext getCurrentInstance(FaceletContext ctx)
52 {
53 if (ctx instanceof AbstractFaceletContext)
54 {
55 return ((AbstractFaceletContext)ctx).getFaceletCompositionContext();
56 }
57 else
58 {
59 // Here we have two choices: retrieve it throught ThreadLocal var
60 // or use the attribute value on FacesContext, but it seems better
61 // use the FacesContext attribute map.
62 return (FaceletCompositionContext)
63 ctx.getFacesContext().getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
64 }
65 }
66
67 static public FaceletCompositionContext getCurrentInstance(FacesContext ctx)
68 {
69 return (FaceletCompositionContext) ctx.getAttributes().get(FACELET_COMPOSITION_CONTEXT_KEY);
70 }
71
72 public void init(FacesContext facesContext)
73 {
74 facesContext.getAttributes().put(
75 FaceletCompositionContext.FACELET_COMPOSITION_CONTEXT_KEY, this);
76 }
77
78 /**
79 * Releases the MyFaceletContext object. This method must only
80 * be called by the code that created the MyFaceletContext.
81 */
82 public void release(FacesContext facesContext)
83 {
84 facesContext.getAttributes().remove(FACELET_COMPOSITION_CONTEXT_KEY);
85 }
86
87 public abstract FaceletFactory getFaceletFactory();
88
89 /**
90 * Return the composite component being applied on the current facelet.
91 *
92 * Note this is different to UIComponent.getCurrentCompositeComponent, because a composite
93 * component is added to the stack each time a composite:implementation tag handler is applied.
94 *
95 * This could be used by InsertChildrenHandler and InsertFacetHandler to retrieve the current
96 * composite component to be applied.
97 *
98 * @since 2.0.1
99 * @return
100 */
101 public abstract UIComponent getCompositeComponentFromStack();
102
103 /**
104 * @since 2.0.1
105 * @param parent
106 */
107 public abstract void pushCompositeComponentToStack(UIComponent parent);
108
109 /**
110 * @since 2.0.1
111 */
112 public abstract void popCompositeComponentToStack();
113
114 /**
115 * Return the latest UniqueIdVendor created from stack. The reason why we need to keep
116 * a UniqueIdVendor stack is because we need to look the closest one in ComponentTagHandlerDelegate.
117 * Note that facelets tree is built from leafs to root, that means use UIComponent.getParent() does not
118 * always return parent components.
119 *
120 * @since 2.0.1
121 * @return
122 */
123 public abstract UniqueIdVendor getUniqueIdVendorFromStack();
124
125 /**
126 * @since 2.0.1
127 * @param parent
128 */
129 public abstract void pushUniqueIdVendorToStack(UniqueIdVendor parent);
130
131 /**
132 * @since 2.0.1
133 */
134 public abstract void popUniqueIdVendorToStack();
135
136 /**
137 * Gets the top of the validationGroups stack.
138 * @return
139 * @since 2.0.1
140 */
141 @Deprecated
142 public abstract String getFirstValidationGroupFromStack();
143
144 /**
145 * Removes top of stack.
146 * @since 2.0.1
147 */
148 @Deprecated
149 public abstract void popValidationGroupsToStack();
150
151 /**
152 * Pushes validationGroups to the stack.
153 * @param validationGroups
154 * @since 2.0.1
155 */
156 @Deprecated
157 public abstract void pushValidationGroupsToStack(String validationGroups);
158
159 /**
160 * Gets all validationIds on the stack.
161 * @return
162 * @since 2.0.1
163 */
164 @Deprecated
165 public abstract Iterator<String> getExcludedValidatorIds();
166
167 /**
168 * Removes top of stack.
169 * @since 2.0.1
170 */
171 @Deprecated
172 public abstract void popExcludedValidatorIdToStack();
173
174 /**
175 * Pushes validatorId to the stack of excluded validatorIds.
176 * @param validatorId
177 * @since 2.0.1
178 */
179 @Deprecated
180 public abstract void pushExcludedValidatorIdToStack(String validatorId);
181
182 /**
183 * Gets all validationIds on the stack.
184 * @return
185 * @since 2.0.1
186 */
187 @Deprecated
188 public abstract Iterator<String> getEnclosingValidatorIds();
189
190 /**
191 * Removes top of stack.
192 * @since 2.0.1
193 */
194 public abstract void popEnclosingValidatorIdToStack();
195
196 /**
197 * Pushes validatorId to the stack of all enclosing validatorIds.
198 * @param validatorId
199 * @since 2.0.1
200 */
201 @Deprecated
202 public abstract void pushEnclosingValidatorIdToStack(String validatorId);
203
204 /**
205 * Pushes validatorId to the stack of all enclosing validatorIds.
206 *
207 * @param validatorId
208 * @param attachedObjectHandler
209 * @since 2.0.10
210 */
211 public abstract void pushEnclosingValidatorIdToStack(String validatorId,
212 EditableValueHolderAttachedObjectHandler attachedObjectHandler);
213
214 /**
215 * Gets all validationIds with its associated EditableValueHolderAttachedObjectHandler from the stack.
216 *
217 * @return
218 * @since 2.0.10
219 */
220 public abstract Iterator<Map.Entry<String, EditableValueHolderAttachedObjectHandler>>
221 getEnclosingValidatorIdsAndHandlers();
222
223 /**
224 *
225 * @param id
226 * @return
227 * @since 2.0.10
228 */
229 public abstract boolean containsEnclosingValidatorId(String id);
230
231 /**
232 * Check if this build is being refreshed, adding transient components
233 * and adding/removing components under c:if or c:forEach or not.
234 *
235 * @return
236 * @since 2.0.1
237 */
238 public abstract boolean isRefreshingTransientBuild();
239
240 /**
241 * Check if this build should be marked as initial state. In other words,
242 * all components must call UIComponent.markInitialState.
243 *
244 * @return
245 * @since 2.0.1
246 */
247 public abstract boolean isMarkInitialState();
248
249 public void setMarkInitialState(boolean value)
250 {
251 }
252
253 /**
254 * Check if the current view will be refreshed with partial state saving.
255 *
256 * This param is used in two posible events:
257 *
258 * 1. To notify UIInstruction instances to look for instances moved by
259 * cc:insertChildren or cc:insertFacet.
260 * 2. To do proper actions when a tag that could change tree structure is applied
261 * (c:if, c:forEach...)
262 *
263 * @return
264 * @since 2.0.1
265 */
266 public abstract boolean isRefreshTransientBuildOnPSS();
267
268 /**
269 *
270 * @since 2.0.12, 2.1.6
271 * @return
272 */
273 public boolean isRefreshTransientBuildOnPSSPreserveState()
274 {
275 return false;
276 }
277
278 /**
279 * Check if we are using partial state saving on this view
280 *
281 * @return
282 * @since 2.0.1
283 */
284 public abstract boolean isUsingPSSOnThisView();
285
286 /**
287 * @since 2.0.1
288 * @return
289 */
290 public abstract boolean isMarkInitialStateAndIsRefreshTransientBuildOnPSS();
291
292 /**
293 * Add to the composite component parent this handler, so it will be processed later when
294 * ViewDeclarationLanguage.retargetAttachedObjects is called.
295 *
296 * Tag Handlers exposing attached objects should call this method to expose them when the
297 * parent to be applied is a composite components.
298 *
299 * @since 2.0.2
300 * @param compositeComponentParent
301 * @param handler
302 */
303 public abstract void addAttachedObjectHandler(UIComponent compositeComponentParent, AttachedObjectHandler handler);
304
305 /**
306 * Remove from the composite component parent the list of attached handlers.
307 *
308 * @since 2.0.2
309 * @param compositeComponentParent
310 */
311 public abstract void removeAttachedObjectHandlers(UIComponent compositeComponentParent);
312
313 /**
314 * Retrieve the list of object handlers attached to a composite component parent.
315 *
316 * @since 2.0.2
317 * @param compositeComponentParent
318 */
319 public abstract List<AttachedObjectHandler> getAttachedObjectHandlers(UIComponent compositeComponentParent);
320
321 /**
322 * Marks all direct children and Facets with an attribute for deletion.
323 *
324 * @since 2.0.2
325 * @see #finalizeForDeletion(UIComponent)
326 * @param component
327 * UIComponent to mark
328 */
329 public abstract void markForDeletion(UIComponent component);
330
331 /**
332 * Used in conjunction with markForDeletion where any UIComponent marked will be removed.
333 *
334 * @since 2.0.2
335 * @param component
336 * UIComponent to finalize
337 */
338 public abstract void finalizeForDeletion(UIComponent component);
339
340 /**
341 * Add a method expression as targeted for the provided composite component
342 *
343 * @since 2.0.3
344 * @param targetedComponent
345 * @param attributeName
346 * @param backingValue A value that could be useful to revert its effects.
347 */
348 public abstract void addMethodExpressionTargeted(UIComponent targetedComponent, String attributeName,
349 Object backingValue);
350
351 /**
352 * Check if the MethodExpression attribute has been applied using vdl.retargetMethodExpression
353 *
354 * @since 2.0.3
355 * @param compositeComponentParent
356 * @param attributeName
357 * @return
358 */
359 public abstract boolean isMethodExpressionAttributeApplied(UIComponent compositeComponentParent,
360 String attributeName);
361
362 /**
363 * Mark the MethodExpression attribute as applied using vdl.retargetMethodExpression
364 *
365 * @since 2.0.3
366 * @param compositeComponentParent
367 * @param attributeName
368 */
369 public abstract void markMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
370
371 /**
372 * Clear the MethodExpression attribute to call vdl.retargetMethodExpression again
373 *
374 * @since 2.0.3
375 * @param compositeComponentParent
376 * @param attributeName
377 */
378 public abstract void clearMethodExpressionAttribute(UIComponent compositeComponentParent, String attributeName);
379
380 /**
381 * Remove a method expression as targeted for the provided composite component
382 *
383 * @since 2.0.3
384 * @param targetedComponent
385 * @param attributeName
386 * @return A value that could be useful to revert its effects.
387 */
388 public abstract Object removeMethodExpressionTargeted(UIComponent targetedComponent, String attributeName);
389
390 /**
391 * Indicates if a EL Expression can be or not cached by facelets vdl.
392 *
393 * @since 2.0.8
394 * @return
395 */
396 public ELExpressionCacheMode getELExpressionCacheMode()
397 {
398 return ELExpressionCacheMode.noCache;
399 }
400
401 /**
402 *
403 * @since 2.0.9
404 * @return
405 */
406 public boolean isWrapTagExceptionsAsContextAware()
407 {
408 return true;
409 }
410
411 /**
412 * Start a new unique id section, which means a new counter is used to
413 * generate unique ids to components
414 *
415 * @since 2.0.10, 2.1.4
416 * @return
417 */
418 public String startComponentUniqueIdSection()
419 {
420 return null;
421 }
422
423 /**
424 * Generate a unique id that will be used later to derive a unique id per tag
425 * by FaceletContext.generateUniqueId(). This generator ensures uniqueness per
426 * view but FaceletContext.generateUniqueId() ensures uniqueness per view and
427 * per facelet hierarchy, so different included facelets will generate different
428 * ids.
429 *
430 * @return
431 */
432 public String generateUniqueId()
433 {
434 return null;
435 }
436
437 public void generateUniqueId(StringBuilder builderToAdd)
438 {
439 }
440
441 /**
442 * Generate a unique id for component instances.
443 *
444 * @return
445 */
446 public String generateUniqueComponentId()
447 {
448 return null;
449 }
450
451 /**
452 * Ends the current unique id section, so the previous counter will be used
453 * to generate unique ids to components.
454 */
455 public void endComponentUniqueIdSection()
456 {
457 }
458
459 /**
460 * Set the iterator used to retrieve unique ids.
461 *
462 * since 2.1.7, 2.0.13
463 * @param uniqueIdsIterator
464 */
465 public void setUniqueIdsIterator(Iterator<String> uniqueIdsIterator)
466 {
467 }
468
469 /**
470 * Activater record unique id mode, so an structure will be
471 * used to hold those values.
472 *
473 * since 2.1.7, 2.0.13
474 */
475 public void initUniqueIdRecording()
476 {
477 }
478
479 /**
480 * Add an unique id to the list if recording is enabled,
481 * if recording is not enabled it has no effect.
482 *
483 * since 2.1.7, 2.0.13
484 * @param uniqueId
485 */
486 public void addUniqueId(String uniqueId)
487 {
488 }
489
490 /**
491 * Return the unique id from the iterator if applies
492 *
493 * since 2.1.7, 2.0.13
494 * @return
495 */
496 public String getUniqueIdFromIterator()
497 {
498 return null;
499 }
500
501 /**
502 * Return the list of unique ids
503 *
504 * since 2.1.7, 2.0.13
505 * @return
506 */
507 public List<String> getUniqueIdList()
508 {
509 return null;
510 }
511
512 /**
513 * Increment the unique id without construct it.
514 *
515 * since 2.1.7, 2.0.13
516 * @return
517 */
518 public void incrementUniqueId()
519 {
520 }
521
522 /**
523 * Check if the view
524 *
525 * since 2.1.7, 2.0.13
526 * @return
527 */
528 public boolean isBuildingViewMetadata()
529 {
530 return FaceletViewDeclarationLanguage.isBuildingViewMetadata(
531 FacesContext.getCurrentInstance());
532 }
533
534 /**
535 * Call this method to indicate a f:metadata section is about to be processed
536 *
537 * since 2.1.7, 2.0.13
538 * @return
539 */
540 public void startMetadataSection()
541 {
542 }
543
544 /**
545 * Call this method to indicate f:metadata section has been already processed
546 *
547 * since 2.1.7, 2.0.13
548 * @return
549 */
550 public void endMetadataSection()
551 {
552 }
553
554 /**
555 * Check if the component is created inside f:metadata section
556 *
557 * since 2.1.7, 2.0.13
558 * @return
559 */
560 public boolean isInMetadataSection()
561 {
562 return false;
563 }
564
565 /**
566 * Check if the section to be processed is being refreshed.
567 *
568 * since 2.1.7, 2.0.13
569 * @return
570 */
571 public boolean isRefreshingSection()
572 {
573 return isRefreshingTransientBuild() || (!isBuildingViewMetadata() && isInMetadataSection());
574 }
575
576 public StringBuilder getSharedStringBuilder()
577 {
578 return new StringBuilder();
579 }
580 }