in impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java [761:914]
public void retargetAttachedObjects(FacesContext context,
UIComponent topLevelComponent, List<AttachedObjectHandler> handlerList)
{
Assert.notNull(context, "context");
Assert.notNull(topLevelComponent, "topLevelComponent");
Assert.notNull(handlerList, "handlerList");
BeanInfo compositeComponentMetadata
= (BeanInfo) topLevelComponent.getAttributes().get(UIComponent.BEANINFO_KEY);
if (compositeComponentMetadata == null)
{
log.severe("Composite component metadata not found for: " + topLevelComponent.getClientId(context));
return;
}
BeanDescriptor compositeComponentDescriptor = compositeComponentMetadata.getBeanDescriptor();
List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)
compositeComponentDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
if (targetList == null || targetList.isEmpty())
{
return;
}
for (int i = 0, size = handlerList.size(); i < size; i++)
{
AttachedObjectHandler currentHandler = handlerList.get(i);
// In the spec javadoc this variable is referred as forAttributeValue, but
// note it is also called curTargetName
String forValue = currentHandler.getFor();
// perf: targetList is always arrayList: see AttachedObjectTargetHandler.apply
// and ClientBehaviorHandler.apply
for (int k = 0, targetsSize = targetList.size(); k < targetsSize; k++)
{
AttachedObjectTarget currentTarget = targetList.get(k);
FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance();
if ((forValue != null && forValue.equals(currentTarget.getName())) &&
((currentTarget instanceof ActionSourceAttachedObjectTarget &&
currentHandler instanceof ActionSourceAttachedObjectHandler) ||
(currentTarget instanceof EditableValueHolderAttachedObjectTarget &&
currentHandler instanceof EditableValueHolderAttachedObjectHandler) ||
(currentTarget instanceof ValueHolderAttachedObjectTarget &&
currentHandler instanceof ValueHolderAttachedObjectHandler)))
{
// perf: getTargets return ArrayList - see getTargets implementations
List<UIComponent> targets = currentTarget.getTargets(topLevelComponent);
for (int l = 0, targetsCount = targets.size(); l < targetsCount; l++)
{
UIComponent component = targets.get(l);
// If we found composite components when traverse the tree
// we have to call this one recursively, because each composite component
// should have its own AttachedObjectHandler list, filled earlier when
// its tag handler is applied.
if (UIComponent.isCompositeComponent(component))
{
// How we obtain the list of AttachedObjectHandler for
// the current composite component? It should be a component
// attribute or retrieved by a key inside component.getAttributes
// map. Since api does not specify any attribute, we suppose
// this is an implementation detail and it should be retrieved
// from component attribute map.
// But this is only the point of the iceberg, because we should
// define how we register attached object handlers in this list.
// ANS: see CompositeComponentResourceTagHandler.
// The current handler should be added to the list, to be chained.
// Note that the inner component should have a target with the same name
// as "for" attribute
mctx.addAttachedObjectHandler(component, currentHandler);
List<AttachedObjectHandler> handlers = mctx.getAttachedObjectHandlers(component);
retargetAttachedObjects(context, component, handlers);
handlers.remove(currentHandler);
}
else
{
currentHandler.applyAttachedObject(context, component);
}
if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
{
component.markInitialState();
}
}
}
else if ((currentTarget instanceof BehaviorHolderAttachedObjectTarget target &&
currentHandler instanceof BehaviorHolderAttachedObjectHandler handler))
{
String eventName = handler.getEventName();
boolean isDefaultEvent = target.isDefaultEvent();
if ((eventName != null && eventName.equals(currentTarget.getName())) ||
(eventName == null && isDefaultEvent))
{
List<UIComponent> targets = currentTarget.getTargets(topLevelComponent);
for (int j = 0, targetssize = targets.size(); j < targetssize; j++)
{
UIComponent component = targets.get(j);
// If we found composite components when traverse the tree
// we have to call this one recursively, because each composite component
// should have its own AttachedObjectHandler list, filled earlier when
// its tag handler is applied.
if (UIComponent.isCompositeComponent(component))
{
if (currentTarget instanceof ClientBehaviorAttachedObjectTarget clientTarget)
{
mctx.addAttachedObjectHandler(component,
new ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper(
(BehaviorHolderAttachedObjectHandler) currentHandler,
clientTarget.getEvent()));
}
else
{
mctx.addAttachedObjectHandler(component, currentHandler);
}
List<AttachedObjectHandler> handlers = mctx.getAttachedObjectHandlers(component);
retargetAttachedObjects(context, component, handlers);
handlers.remove(currentHandler);
}
else
{
if (currentHandler instanceof
ClientBehaviorRedirectBehaviorAttachedObjectHandlerWrapper wrapper)
{
currentHandler.applyAttachedObject(context,
new ClientBehaviorRedirectEventComponentWrapper(
topLevelComponent,
component,
wrapper.getWrappedEventName(),
eventName,
null));
}
else
{
currentHandler.applyAttachedObject(context, component);
}
}
if (mctx.isUsingPSSOnThisView() && mctx.isMarkInitialState())
{
component.markInitialState();
}
}
}
}
}
}
}