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: struberg $)
41   * @version $Revision: 1194849 $ $Date: 2011-10-29 04:28:45 -0500 (Sat, 29 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
130                 = FaceletCompositionContext.getCurrentInstance(ctx).getCompositeComponentFromStack();
131 
132         CompositeComponentBeanInfo beanInfo = 
133             (CompositeComponentBeanInfo) compositeBaseParent.getAttributes()
134             .get(UIComponent.BEANINFO_KEY);
135         
136         if (beanInfo == null)
137         {
138             if (log.isLoggable(Level.SEVERE))
139             {
140                 log.severe("Cannot find composite bean descriptor UIComponent.BEANINFO_KEY ");
141             }
142             return;
143         }
144         
145         BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor(); 
146         
147         //1. Obtain the list mentioned as "targetList" on ViewDeclarationLanguage.retargetAttachedObjects
148         List<AttachedObjectTarget> targetList = (List<AttachedObjectTarget>)
149             beanDescriptor.getValue(
150                     AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
151         
152         if (targetList == null)
153         {
154             //2. If not found create it and set
155             targetList = new ArrayList<AttachedObjectTarget>();
156             beanDescriptor.setValue(
157                     AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY,
158                     targetList);
159         }
160         
161         //3. Create the instance of AttachedObjectTarget
162         if (isCacheable())
163         {
164             if (_target == null)
165             {
166                 _target = createAttachedObjectTarget(ctx);
167             }
168             targetList.add(_target);
169         }
170         else
171         {
172             ClientBehaviorAttachedObjectTargetImpl target = createAttachedObjectTarget(ctx);
173             targetList.add(target);
174         }
175         
176         this.nextHandler.apply(ctx, parent);
177     }
178     
179     public boolean isCacheable()
180     {
181         return _cacheable;
182     }
183     
184     public void setCacheable(boolean cacheable)
185     {
186         _cacheable = cacheable;
187     }
188 
189     /**
190      * Create a new AttachedObjectTarget instance to be added on the 
191      * target list.
192      * 
193      * @return
194      */
195     protected ClientBehaviorAttachedObjectTargetImpl createAttachedObjectTarget(FaceletContext ctx)
196     {
197         ClientBehaviorAttachedObjectTargetImpl target = new ClientBehaviorAttachedObjectTargetImpl();
198         
199         if (_event != null)
200         {
201             target.setEvent(_event.getValueExpression(ctx, String.class));
202         }
203         if (_name != null)
204         {
205             target.setName(_name.getValueExpression(ctx, String.class));
206         }
207         if (_default != null)
208         {
209             target.setDefault(_default.getBoolean(ctx));
210         }
211         if (_targets != null)
212         {
213             target.setTargets(_targets.getValueExpression(ctx, String.class));
214         }
215         return target;
216     }
217 }