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.composite;
20  
21  import java.beans.BeanDescriptor;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.logging.Level;
26  import java.util.logging.Logger;
27  
28  import javax.faces.component.UIComponent;
29  import javax.faces.view.AttachedObjectTarget;
30  import javax.faces.view.facelets.FaceletContext;
31  import javax.faces.view.facelets.TagAttribute;
32  import javax.faces.view.facelets.TagConfig;
33  import javax.faces.view.facelets.TagHandler;
34  
35  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
36  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
37  import org.apache.myfaces.view.facelets.FaceletCompositionContext;
38  
39  /**
40   * @author Leonardo Uribe (latest modification by $Author: bommel $)
41   * @version $Revision: 1187700 $ $Date: 2011-10-22 07:19:37 -0500 (Sat, 22 Oct 2011) $
42   */
43  @JSFFaceletTag(name="composite:clientBehavior")
44  public class ClientBehaviorHandler extends TagHandler implements InterfaceDescriptorCreator
45  {
46      
47      private static final Logger log = Logger.getLogger(ClientBehaviorHandler.class.getName());
48      
49      /**
50       * This attribute is used as the target event 
51       * name, so client behaviors pointing to "name" 
52       * will be attached on the related components 
53       * identified by "targets" attribute and on 
54       * the event name this attribute holds. In other
55       * words, this is the "real" event name.
56       */
57      @JSFFaceletAttribute(name="event",
58              className="javax.el.ValueExpression",
59              deferredValueType="java.lang.String",
60              required=true)
61      protected final TagAttribute _event;
62  
63      /**
64       * This attribute represents the source event name 
65       * that is used when instances of the composite 
66       * component are used. In other
67       * words, this is the "logical" event name.
68       * 
69       */
70      @JSFFaceletAttribute(name="name",
71              className="javax.el.ValueExpression",
72              deferredValueType="java.lang.String",
73              required=true)
74      protected final TagAttribute _name;
75      
76      /**
77       * Indicate this clientBehavior description is the one
78       * that has to be taken by default. There should be only
79       * one clientBehavior with this property set to true in
80       * a composite component interface description.
81       */
82      @JSFFaceletAttribute(name="default",
83              className="javax.el.ValueExpression",
84              deferredValueType="boolean")
85      protected final TagAttribute _default;
86  
87      /**
88       * Contains a list of clientIds separated by spaces that 
89       * identify the component(s) that will be used to attach 
90       * client behaviors from the composite component.
91       * 
92       */
93      @JSFFaceletAttribute(name="targets",
94              className="javax.el.ValueExpression",
95              deferredValueType="java.lang.String")
96      protected final TagAttribute _targets;
97  
98      /**
99       * Check if the PropertyDescriptor instance created by this handler
100      * can be cacheable or not. 
101      */
102     private boolean _cacheable;
103     
104     private ClientBehaviorAttachedObjectTargetImpl _target;
105 
106     public ClientBehaviorHandler(TagConfig config)
107     {
108         super(config);
109         _name = getRequiredAttribute("name");
110         _event = getAttribute("event");
111         _default = getAttribute("default");
112         _targets = getAttribute("targets");
113         if (_name.isLiteral() && 
114             (_event == null || _event.isLiteral()) &&
115             (_default == null || _default.isLiteral() ))
116         {
117             _cacheable = true;
118         }
119         else
120         {
121             _cacheable = false;
122         }
123     }
124 
125     @SuppressWarnings("unchecked")
126     public void apply(FaceletContext ctx, UIComponent parent)
127             throws IOException
128     {
129         UIComponent compositeBaseParent = FaceletCompositionContext.getCurrentInstance(ctx).getCompositeComponentFromStack();
130 
131         CompositeComponentBeanInfo beanInfo = 
132             (CompositeComponentBeanInfo) compositeBaseParent.getAttributes()
133             .get(UIComponent.BEANINFO_KEY);
134         
135         if (beanInfo == null)
136         {
137             if (log.isLoggable(Level.SEVERE))
138             {
139                 log.severe("Cannot find composite bean descriptor UIComponent.BEANINFO_KEY ");
140             }
141             return;
142         }
143         
144         BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor(); 
145         
146         //1. Obtain the list mentioned as "targetList" on ViewDeclarationLanguage.retargetAttachedObjects
147         List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)
148             beanDescriptor.getValue(
149                     AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
150         
151         if (targetList == null)
152         {
153             //2. If not found create it and set
154             targetList = new ArrayList<AttachedObjectTarget>();
155             beanDescriptor.setValue(
156                     AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY,
157                     targetList);
158         }
159         
160         //3. Create the instance of AttachedObjectTarget
161         if (isCacheable())
162         {
163             if (_target == null)
164             {
165                 _target = createAttachedObjectTarget(ctx);
166             }
167             targetList.add(_target);
168         }
169         else
170         {
171             ClientBehaviorAttachedObjectTargetImpl target = createAttachedObjectTarget(ctx);
172             targetList.add(target);
173         }
174         
175         this.nextHandler.apply(ctx, parent);
176     }
177     
178     public boolean isCacheable()
179     {
180         return _cacheable;
181     }
182     
183     public void setCacheable(boolean cacheable)
184     {
185         _cacheable = cacheable;
186     }
187 
188     /**
189      * Create a new AttachedObjectTarget instance to be added on the 
190      * target list.
191      * 
192      * @return
193      */
194     protected ClientBehaviorAttachedObjectTargetImpl createAttachedObjectTarget(FaceletContext ctx)
195     {
196         ClientBehaviorAttachedObjectTargetImpl target = new ClientBehaviorAttachedObjectTargetImpl();
197         
198         if (_event != null)
199         {
200             target.setEvent(_event.getValueExpression(ctx, String.class));
201         }
202         if (_name != null)
203         {
204             target.setName(_name.getValueExpression(ctx, String.class));
205         }
206         if (_default != null)
207         {
208             target.setDefault(_default.getBoolean(ctx));
209         }
210         if (_targets != null)
211         {
212             target.setTargets(_targets.getValueExpression(ctx, String.class));
213         }
214         return target;
215     }
216 }