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.tag.jsf.core;
20  
21  import java.io.IOException;
22  import java.io.Serializable;
23  
24  import javax.el.ELContext;
25  import javax.el.ELException;
26  import javax.el.ExpressionFactory;
27  import javax.el.ValueExpression;
28  import javax.faces.FacesException;
29  import javax.faces.component.ActionSource;
30  import javax.faces.component.UIComponent;
31  import javax.faces.context.FacesContext;
32  import javax.faces.event.AbortProcessingException;
33  import javax.faces.event.ActionEvent;
34  import javax.faces.event.ActionListener;
35  import javax.faces.view.ActionSource2AttachedObjectHandler;
36  import javax.faces.view.facelets.ComponentHandler;
37  import javax.faces.view.facelets.FaceletContext;
38  import javax.faces.view.facelets.FaceletException;
39  import javax.faces.view.facelets.TagAttribute;
40  import javax.faces.view.facelets.TagConfig;
41  import javax.faces.view.facelets.TagException;
42  import javax.faces.view.facelets.TagHandler;
43  
44  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
45  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
46  import org.apache.myfaces.view.facelets.FaceletCompositionContext;
47  
48  @JSFFaceletTag(
49          name = "f:setPropertyActionListener",
50          bodyContent = "empty", 
51          tagClass="org.apache.myfaces.taglib.core.SetPropertyActionListenerTag")
52  public class SetPropertyActionListenerHandler extends TagHandler
53      implements ActionSource2AttachedObjectHandler 
54  {
55      private final TagAttribute _target;
56      private final TagAttribute _value;
57  
58      public SetPropertyActionListenerHandler(TagConfig config)
59      {
60          super(config);
61          this._value = this.getRequiredAttribute("value");
62          this._target = this.getRequiredAttribute("target");
63      }
64  
65      public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
66              ELException
67      {
68          //Apply only if we are creating a new component
69          if (!ComponentHandler.isNew(parent))
70          {
71              return;
72          }
73          if (parent instanceof ActionSource)
74          {
75              applyAttachedObject(ctx.getFacesContext(), parent);
76          }
77          else if (UIComponent.isCompositeComponent(parent))
78          {
79              FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
80              mctx.addAttachedObjectHandler(parent, this);
81          }
82          else
83          {
84              throw new TagException(this.tag, "Parent is not composite component or of type ActionSource, type is: " + parent);
85          }
86      }
87  
88      private static class SetPropertyListener implements ActionListener, Serializable
89      {
90          private ValueExpression _target;
91          private ValueExpression _value;
92  
93          public SetPropertyListener()
94          {
95          };
96  
97          public SetPropertyListener(ValueExpression value, ValueExpression target)
98          {
99              _value = value;
100             _target = target;
101         }
102 
103         public void processAction(ActionEvent evt) throws AbortProcessingException
104         {
105             FacesContext facesContext = FacesContext.getCurrentInstance();
106             
107             ELContext elContext = facesContext.getELContext();
108             
109             // Spec f:setPropertyActionListener: 
110             
111             // Call getValue() on the "value" ValueExpression.
112             Object value = _value.getValue(elContext);
113             
114             // If value of the "value" expression is null, call setValue() on the "target" ValueExpression with the null
115             
116             // If the value of the "value" expression is not null, call getType()on the "value" and "target"
117             // ValueExpressions to determine their property types.
118             if (value != null)
119             {
120                 Class<?> targetType = _target.getType(elContext);
121                 // Spec says: "all getType() on the "value" to determine  property type" but it is not necessary
122                 // beacuse type we have objValue already
123 
124                 //   Coerce the value of the "value" expression to the "target" expression value type following the Expression
125                 // Language coercion rules. 
126                 ExpressionFactory expressionFactory = facesContext.getApplication().getExpressionFactory();
127                 value = expressionFactory.coerceToType(value, targetType);
128             }
129 
130             // Call setValue()on the "target" ValueExpression with the resulting value.
131             _target.setValue(elContext, value);
132         }
133     }
134 
135     public void applyAttachedObject(FacesContext context, UIComponent parent)
136     {
137         // Retrieve the current FaceletContext from FacesContext object
138         FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(
139                 FaceletContext.FACELET_CONTEXT_KEY);
140 
141         ActionSource src = (ActionSource) parent;
142         ValueExpression valueExpr = _value.getValueExpression(faceletContext, Object.class);
143         ValueExpression targetExpr = _target.getValueExpression(faceletContext, Object.class);
144 
145         src.addActionListener(new SetPropertyListener(valueExpr, targetExpr));
146     }
147 
148     /**
149      * TODO: Document me!
150      */
151     @JSFFaceletAttribute
152     public String getFor()
153     {
154         TagAttribute forAttribute = getAttribute("for");
155         
156         if (forAttribute == null)
157         {
158             return null;
159         }
160         else
161         {
162             return forAttribute.getValue();
163         }
164     }
165 }