1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets.tag.composite;
20
21 import java.beans.IntrospectionException;
22 import java.beans.PropertyDescriptor;
23 import java.io.IOException;
24 import java.util.List;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27
28 import javax.faces.application.ProjectStage;
29 import javax.faces.component.UIComponent;
30 import javax.faces.context.FacesContext;
31 import javax.faces.view.facelets.FaceletContext;
32 import javax.faces.view.facelets.TagAttribute;
33 import javax.faces.view.facelets.TagConfig;
34 import javax.faces.view.facelets.TagException;
35 import javax.faces.view.facelets.TagHandler;
36
37 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
38 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
39 import org.apache.myfaces.shared.util.ClassUtils;
40 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
41
42
43
44
45
46 @JSFFaceletTag(name="composite:attribute")
47 public class AttributeHandler extends TagHandler implements InterfaceDescriptorCreator
48 {
49
50 private static final Logger log = Logger.getLogger(AttributeHandler.class.getName());
51
52
53
54
55
56 private static final String[] STANDARD_ATTRIBUTES_SORTED = new String[]
57 {
58 "default",
59 "displayName",
60 "expert",
61 "hidden",
62 "method-signature",
63 "name",
64 "preferred",
65 "required",
66 "shortDescription",
67 "targetAttributeName",
68 "targets",
69 "type"
70 };
71
72 @JSFFaceletAttribute(name="name",
73 className="javax.el.ValueExpression",
74 deferredValueType="java.lang.String",
75 required=true)
76 private final TagAttribute _name;
77
78 @JSFFaceletAttribute(name="targets",
79 className="javax.el.ValueExpression",
80 deferredValueType="java.lang.String")
81 private final TagAttribute _targets;
82
83
84
85
86
87
88 @JSFFaceletAttribute(name="default",
89 className="javax.el.ValueExpression",
90 deferredValueType="java.lang.String")
91 private final TagAttribute _default;
92
93
94
95
96 @JSFFaceletAttribute(name="displayName",
97 className="javax.el.ValueExpression",
98 deferredValueType="java.lang.String")
99 private final TagAttribute _displayName;
100
101
102
103
104
105
106
107 @JSFFaceletAttribute(name="required",
108 className="javax.el.ValueExpression",
109 deferredValueType="boolean")
110 private final TagAttribute _required;
111
112
113
114
115 @JSFFaceletAttribute(name="preferred",
116 className="javax.el.ValueExpression",
117 deferredValueType="boolean")
118 private final TagAttribute _preferred;
119
120
121
122
123 @JSFFaceletAttribute(name="expert",
124 className="javax.el.ValueExpression",
125 deferredValueType="boolean")
126 private final TagAttribute _expert;
127
128
129
130
131 @JSFFaceletAttribute(name="shortDescription",
132 className="javax.el.ValueExpression",
133 deferredValueType="java.lang.String")
134 private final TagAttribute _shortDescription;
135
136 @JSFFaceletAttribute(name="method-signature",
137 className="javax.el.ValueExpression",
138 deferredValueType="java.lang.String")
139 private final TagAttribute _methodSignature;
140
141 @JSFFaceletAttribute(name="type",
142 className="javax.el.ValueExpression",
143 deferredValueType="java.lang.String")
144 private final TagAttribute _type;
145
146
147
148
149
150
151 @JSFFaceletAttribute(name="hidden",
152 className="javax.el.ValueExpression",
153 deferredValueType="boolean")
154 protected final TagAttribute _hidden;
155
156 @JSFFaceletAttribute(name="targetAttributeName",
157 className="javax.el.ValueExpression",
158 deferredValueType="java.lang.String")
159 private final TagAttribute _targetAttributeName;
160
161
162
163
164
165 private boolean _cacheable;
166
167
168
169
170
171
172
173
174 private PropertyDescriptor _propertyDescriptor;
175
176 public AttributeHandler(TagConfig config)
177 {
178 super(config);
179 _name = getRequiredAttribute("name");
180 _targets = getAttribute("targets");
181 _default = getAttribute("default");
182 _displayName = getAttribute("displayName");
183 _required = getAttribute("required");
184 _preferred = getAttribute("preferred");
185 _expert = getAttribute("expert");
186 _shortDescription = getAttribute("shortDescription");
187 _methodSignature = getAttribute("method-signature");
188 _type = getAttribute("type");
189 _hidden = getAttribute("hidden");
190 _targetAttributeName = getAttribute("targetAttributeName");
191
192
193
194
195
196
197 final boolean development = FacesContext.getCurrentInstance()
198 .isProjectStage(ProjectStage.Development);
199
200 if (_name.isLiteral()
201 && (!development || _areDevelopmentAttributesLiteral()))
202 {
203
204
205
206
207
208
209 _cacheable = true;
210 if ( _targets == null && _default == null && _required == null &&
211 _methodSignature == null && _type == null && _targetAttributeName == null &&
212 !CompositeTagAttributeUtils.containsUnspecifiedAttributes(tag,
213 STANDARD_ATTRIBUTES_SORTED))
214 {
215 _propertyDescriptor = _createPropertyDescriptor(development);
216 }
217 }
218 else
219 {
220 _cacheable = false;
221 }
222 }
223
224
225
226
227
228
229 private boolean _areDevelopmentAttributesLiteral()
230 {
231 return CompositeTagAttributeUtils.areAttributesLiteral(
232 _displayName, _shortDescription, _expert, _hidden, _preferred);
233 }
234
235 public void apply(FaceletContext ctx, UIComponent parent)
236 throws IOException
237 {
238 UIComponent compositeBaseParent
239 = FaceletCompositionContext.getCurrentInstance(ctx).getCompositeComponentFromStack();
240
241 CompositeComponentBeanInfo beanInfo =
242 (CompositeComponentBeanInfo) compositeBaseParent.getAttributes()
243 .get(UIComponent.BEANINFO_KEY);
244
245 if (beanInfo == null)
246 {
247 if (log.isLoggable(Level.SEVERE))
248 {
249 log.severe("Cannot find composite bean descriptor UIComponent.BEANINFO_KEY ");
250 }
251 return;
252 }
253
254 List<PropertyDescriptor> attributeList = beanInfo.getPropertyDescriptorsList();
255
256 if (isCacheable())
257 {
258 if (_propertyDescriptor == null)
259 {
260 _propertyDescriptor = _createPropertyDescriptor(ctx);
261 }
262 attributeList.add(_propertyDescriptor);
263 }
264 else
265 {
266 PropertyDescriptor attribute = _createPropertyDescriptor(ctx);
267 attributeList.add(attribute);
268 }
269
270
271
272
273
274 }
275
276
277
278
279
280
281
282
283 private PropertyDescriptor _createPropertyDescriptor(boolean development)
284 {
285 try
286 {
287 CompositeComponentPropertyDescriptor attributeDescriptor =
288 new CompositeComponentPropertyDescriptor(_name.getValue());
289
290
291
292 if (development)
293 {
294 CompositeTagAttributeUtils.addDevelopmentAttributesLiteral(attributeDescriptor,
295 _displayName, _shortDescription, _expert, _hidden, _preferred);
296 }
297
298
299
300
301 return attributeDescriptor;
302 }
303 catch (IntrospectionException e)
304 {
305 if (log.isLoggable(Level.SEVERE))
306 {
307 log.log(Level.SEVERE, "Cannot create PropertyDescriptor for attribute ",e);
308 }
309 throw new TagException(tag,e);
310 }
311 }
312
313 private PropertyDescriptor _createPropertyDescriptor(FaceletContext ctx)
314 throws TagException, IOException
315 {
316 try
317 {
318 CompositeComponentPropertyDescriptor attributeDescriptor =
319 new CompositeComponentPropertyDescriptor(_name.getValue(ctx));
320
321
322
323 if (_targets != null)
324 {
325 attributeDescriptor.setValue("targets", _targets.getValueExpression(ctx, String.class));
326 }
327 if (_default != null)
328 {
329 if (_type != null)
330 {
331 Class clazz = String.class;
332
333 String type = _type.getValue(ctx);
334 if (type != null && !type.trim().isEmpty())
335 {
336 try
337 {
338 clazz = ClassUtils.javaDefaultTypeToClass(type);
339 }
340 catch (ClassNotFoundException e)
341 {
342 log.log(Level.WARNING,
343 "composite:attribute 'type' with value'" + type + "' not resolveable. "
344 + "Fallback to string.",
345 e);
346 }
347 }
348
349 if (_default.isLiteral())
350 {
351
352 attributeDescriptor.setValue("default", _default.getObject(ctx, clazz));
353 }
354 else
355 {
356 attributeDescriptor.setValue("default", _default.getValueExpression(ctx, clazz));
357 }
358 }
359 else
360 {
361 attributeDescriptor.setValue("default", _default.getValueExpression(ctx, String.class));
362 }
363 }
364 if (_required != null)
365 {
366 attributeDescriptor.setValue("required", _required.getValueExpression(ctx, Boolean.class));
367 }
368 if (_methodSignature != null)
369 {
370 attributeDescriptor.setValue("method-signature",
371 _methodSignature.getValueExpression(ctx, String.class));
372 }
373 if (_type != null)
374 {
375 attributeDescriptor.setValue("type", _type.getValueExpression(ctx, String.class));
376 }
377 if (_targetAttributeName != null)
378 {
379 attributeDescriptor.setValue("targetAttributeName",
380 _targetAttributeName.getValueExpression(ctx, String.class));
381 }
382
383
384
385 if (ctx.getFacesContext().isProjectStage(ProjectStage.Development))
386 {
387 CompositeTagAttributeUtils.addDevelopmentAttributes(attributeDescriptor, ctx,
388 _displayName, _shortDescription, _expert, _hidden, _preferred);
389 }
390
391
392
393 CompositeTagAttributeUtils.addUnspecifiedAttributes(attributeDescriptor, tag,
394 STANDARD_ATTRIBUTES_SORTED, ctx);
395
396 return attributeDescriptor;
397 }
398 catch (IntrospectionException e)
399 {
400 if (log.isLoggable(Level.SEVERE))
401 {
402 log.log(Level.SEVERE, "Cannot create PropertyDescriptor for attribute ",e);
403 }
404 throw new TagException(tag,e);
405 }
406 }
407
408 public boolean isCacheable()
409 {
410 return _cacheable;
411 }
412
413 public void setCacheable(boolean cacheable)
414 {
415 _cacheable = cacheable;
416 }
417 }