Hi

2010/10/19 Ed Burns <edward.burns@oracle.com>
>>>>> On Mon, 18 Oct 2010 20:36:06 -0500, Leonardo Uribe <lu4242@gmail.com> said:

[...]

LU> There are two possible alternatives here:

LU>  1. Implement the algorithm proposed for retargetMethodExpressions
LU> and ignore composite:attribute "targets" property says.

LU>  2. Implement the expected behavior of composite:attribute "targets"
LU> property and make some changes to retargetMethodExpressions
LU> algorithm.

LU> The intention is take option 2 and include it for JSF 2.0, because
LU> in theory should be handled as an implementation detail of the
LU> algorithm (anyway it could be good to update the documentation with
LU> the same advice used for retargetAttachedObjects).

Certainly you have identified a valid issue.  The root problem is that
the top level component needs to have a Java programming way to expose
its composite-ness.

LU> For "action", "actionListener", "validator" and
LU> "valueChangeListener" it is clear that the action to take is
LU> something like this:

LU>  - If target is a composite component and that one "retarget" to
LU> other components and additionally does not implements
LU> [ActionSource2/EditableValueHolder], call:

LU>    targetComponent.getAttributes().put(attributeName,
LU> attributeNameValueExpression);

LU>    and call retargetMethodExpressions recursively. Take care of
LU> apply the method twice and if the property pointed by
LU> "attributeName" was already set, revert its effects.

The solution you propose will work, but it feels a bit too
implementation-ish.  Right now we declare that every compositeComponent
must be a NamingContainer.  Perhaps it's time to define a new abstract
sub-class of NamingContainer that is a union of all the behavioral
interfaces?

public abstract class javax.faces.component.CompositeComponent
implements NamingContainer, ActionSource2, EditableValueHolder {
 public abstract void acceptRetargetedMethodExpressions(BeanInfo
   ccMetadata);
}


I like the way it works now. For example, tomahawk t:inputHtml component was
rewritten into a composite component, and it is a good example about when it could
be useful that the only requerimiento for a component to be composite is implement
NamingContainer:

<composite:interface componentType="org.apache.myfaces.InputHtml">

public class InputHtml extends HtmlInputText implements NamingContainer, UniqueIdVendor {

In my understanding, if a composite component base class implements a behavioral interface,
(ActionSource2, EditableValueHolder, ...), "targets" behavior must not be allowed, because
the code handling that will be on the base class. In the example shown InputHtml extends
from HtmlInputText, so it implements EditableValueHolder.

To decide when "targets" behavior applies I have something like this:

if (isCompositeComponentRetarget(context, innerComponent, attributeName) && !(innerComponent instanceof ActionSource2))
{
   //cc retarget
}
else
{
  //process on innerComponent
}

isCompositeComponentRetarget do two things:

- Check if the component is a composite one.
- Check if the attribute was defined looking on the BeanInfo.

Leonardo

LU> The tricky part is how to handle generic method expression
LU> properties. The javadoc says:

We could specify whatever we needed in that
acceptRetargetedMethodExpressions() method.

Ed

--
| edward.burns@oracle.com | office: +1 407 458 0017
| homepage:               | http://ridingthecrest.com/
| 16 work days until German Oracle User's Group Conference