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.trinidad.skin;
20  
21  import java.util.Map;
22  
23  import javax.el.ValueExpression;
24  
25  import javax.faces.el.ValueBinding;
26  
27  import org.apache.myfaces.trinidad.util.ToStringHelper;
28  
29  /**
30   * <p>
31   * SkinAddition objects are used by custom component developers who have created custom
32   * components, and they need a way to 'push' in their own stylesheet and
33   * resource bundle for these components into some skin of their choosing,
34   * most likely the simple skin.</p>
35   * <p>
36   * A Skin object contains zero or more SkinAdditions. The SkinAdditions' stylesheets
37   * are merged into the Skin's own stylesheet. The SkinAdditions' resource
38   * bundle is looked at along with the Skin's own resource bundle when Skin's
39   * getTranslatedValue is called.
40   * </p>
41   * <p>
42   * If you want to 'push' your styles into a specific skin, then you would create a skin-addition in the trinidad-skins.xml file.
43   * You specify a &lt;skin-addition&gt;. The children are: &lt;skin-id&gt;,
44   * &lt;style-sheet-name&gt;, &lt;bundle-name&gt;, and &lt;translation-source&gt;.
45   * The &lt;skin-id&gt; is used to specify which skin you want to 'push' your stylesheet/resource bundle into.
46   * Most likely this is the simple.desktop skin.
47   * The other elements are used to create a SkinAddition object.
48   * </p>
49   */
50  public class SkinAddition implements Comparable
51  {
52  
53    /**
54     * Constructor takes a styleSheet name and a resourceBundle name.
55     * @deprecated Use builder to create a SkinAddition object.
56     * @See Builder
57     */
58    @Deprecated
59    public SkinAddition (
60      String styleSheetName,
61      String resourceBundleName
62      )
63    {
64      _styleSheetName = styleSheetName;
65      _resourceBundleName = resourceBundleName;
66      _translationSourceVE = null;
67      _translationSourceVB = null;
68      _skinFeatures = null;
69      _skinId = null;
70    }
71  
72    /**
73     * Constructor takes a styleSheet name and a translationSource ValueExpression.
74     * @deprecated Use builder to create a SkinAddition object.
75     * @See Builder
76     */
77    @Deprecated
78    public SkinAddition (
79      String       styleSheetName,
80      ValueExpression translationSourceValueExpression
81      )
82    {
83      _styleSheetName = styleSheetName;
84      _resourceBundleName = null;
85      _translationSourceVE = translationSourceValueExpression;
86      _translationSourceVB = null;
87      _skinFeatures = null;
88      _skinId = null;
89    }
90    /**
91     * Constructor takes a styleSheet name. resource bundle name and
92     * translation source value expression will be null.
93     * @deprecated Use builder to create a SkinAddition object.
94     * @See Builder
95     */
96    @Deprecated
97    public SkinAddition (
98      String styleSheetName
99      )
100   {
101     _styleSheetName = styleSheetName;
102     _resourceBundleName = null;
103     _translationSourceVE = null;
104     _translationSourceVB = null;
105     _skinFeatures = null;
106     _skinId = null;
107   }
108 
109   /**
110    * Constructor takes a styleSheet name and a resourceBundle name.
111    * @deprecated Use builder to create a SkinAddition object.
112    * @See Builder
113    */
114   @Deprecated
115   public SkinAddition (
116     String styleSheetName,
117     String resourceBundleName,
118     Map<String, String> features
119     )
120   {
121     _styleSheetName = styleSheetName;
122     _resourceBundleName = resourceBundleName;
123     _translationSourceVE = null;
124     _translationSourceVB = null;
125     _skinFeatures = features;
126     _skinId = null;
127   }
128 
129   /**
130    * Constructor takes a styleSheet name and a translationSource ValueExpression.
131    * @deprecated Use builder to create a SkinAddition object.
132    * @See Builder
133    */
134   @Deprecated
135   public SkinAddition (
136     String       styleSheetName,
137     ValueExpression translationSourceValueExpression,
138     Map<String, String> features
139     )
140   {
141     _styleSheetName = styleSheetName;
142     _resourceBundleName = null;
143     _translationSourceVE = translationSourceValueExpression;
144     _translationSourceVB = null;
145     _skinFeatures = features;
146     _skinId = null;
147   }
148   /**
149    * Constructor takes a styleSheet name. resource bundle name and
150    * translation source value expression will be null.
151    * @deprecated Use builder to create a SkinAddition object.
152    * @See Builder
153    */
154   @Deprecated
155   public SkinAddition (
156     String styleSheetName,
157     Map<String, String> features
158     )
159   {
160     _styleSheetName = styleSheetName;
161     _resourceBundleName = null;
162     _translationSourceVE = null;
163     _translationSourceVB = null;
164     _skinFeatures = features;
165     _skinId = null;
166   }
167 
168   /**
169    * Constructor takes only features.
170    * @deprecated Use builder to create a SkinAddition object.
171    * @See Builder
172    */
173   @Deprecated
174   public SkinAddition (
175     Map<String, String> features
176     )
177   {
178     _styleSheetName = null;
179     _resourceBundleName = null;
180     _translationSourceVE = null;
181     _translationSourceVB = null;
182     _skinFeatures = features;
183     _skinId = null;
184   }
185 
186   /**
187    * Constructor takes a styleSheet name and a translationSource ValueBinding.
188    * ValueBinding is deprecated, use ValueExpression for setting the translationSource
189    * @deprecated Use builder to create a SkinAddition object.
190    * @See Builder
191    */
192   @Deprecated
193   public SkinAddition (
194     String       styleSheetName,
195     ValueBinding translationSourceValueBinding
196     )
197   {
198     _styleSheetName = styleSheetName;
199     _resourceBundleName = null;
200     _translationSourceVE = null;
201     _translationSourceVB = translationSourceValueBinding;
202     _skinFeatures = null;
203     _skinId = null;
204   }
205 
206   /**
207    * Gets the skin id to which this skin addition belongs to.
208    */
209   public String getSkinId()
210   {
211     return _skinId;
212   }
213   
214   /**
215    * Gets the SkinAddition's style sheet name.
216    * Note that in order to avoid infinite call loop the implementation of getStylesheetName() in 
217    * this class or sub classes should not call toString().
218    */
219   public String getStyleSheetName()
220   {
221     return _styleSheetName;
222   }
223   
224   /**
225    * Gets the SkinAddition's resource bundle. 
226    * A skin cannot have both a resourceBundleName and a translation source
227    * value expression. If they do, then the resourceBundleName takes precedence.
228    * Note that in order to avoid infinite call loop the implementation of getResourceBundleName() 
229    * in this class or sub classes should not call toString().
230    */
231   public String getResourceBundleName()
232   {
233     return _resourceBundleName;
234   } 
235 
236   /**
237    * @inheritDoc
238    * Note that in order to avoid infinite call loop the implementation of getStyleSheetName() 
239    * and getResourceBundleName() in this class or its sub classes should not call toString().
240    */
241   @Override
242   public String toString()
243   {
244     ToStringHelper helper = 
245       new ToStringHelper(this).
246       append("styleSheetName", getStyleSheetName()).
247       append("bundleName", getResourceBundleName());
248 
249     if (_translationSourceVE != null)
250     {
251       helper.append("translationExpr",  _translationSourceVE.getExpressionString());
252     }
253 
254     if (_translationSourceVB != null)
255     {
256       helper.append("translationBindingExpr",  _translationSourceVB.getExpressionString());
257     }
258 
259     return helper.toString();
260   }
261  
262   
263   /**
264    * Gets the SkinAddition's translation source ValueExpresion. The 
265    * ValueExpression can point to a Map or a ResourceBundle.
266    * Note: A skin cannot have both a resourceBundleName and a translation source
267    * value expression. If they do, then the resourceBundleName takes precedence.
268    */
269   public ValueExpression getTranslationSourceValueExpression()
270   {
271     return _translationSourceVE;
272   } 
273   
274   /**
275    * Gets the SkinAddition's translation source ValueBinding. The 
276    * ValueBinding can point to a Map or a ResourceBundle.
277    * Note: A skin cannot have both a resourceBundleName and a translation source
278    * value binding. If they do, then the resourceBundleName takes precedence.
279    * @deprecated
280    */
281   @Deprecated
282   public ValueBinding getTranslationSourceValueBinding()
283   {
284     return _translationSourceVB;
285   }
286 
287   /**
288    * Gets any skin features added through the skin addition
289    */
290   public Map<String, String> getSkinFeatures()
291   {
292     return _skinFeatures;
293   }
294 
295   /**
296    * Compares two skinning additions for the purposes of ordering.  Currently this
297    * method compares the stylesheet name.  If both names are null, then they are
298    * considered equal.  If one of the names is null and the other isn't, the null
299    * value is always less then the real value.  Other then that the values will be
300    * returned according to the string's natural order.
301    * 
302    * @param t
303    * @return
304    * 
305    * @throws NullPointerException if t is null
306    * @throws ClassCastException id t is not an instance of StyleSheetAddition
307    */
308   public int compareTo(Object t)
309   {
310     String comparedName = ((SkinAddition)t).getStyleSheetName();
311     String thisName     = getStyleSheetName();
312     
313     
314     if(null == thisName)
315     {
316       if(null == comparedName)
317       {
318         //Both stylesheet names are null, so they are equal
319         return 0;
320       }
321       
322       //This stylesheet name is null and the other isn't.  This is always less
323       return -1;
324     }
325     
326     if(null == comparedName)
327     {
328       //Compared object is null, this one isn't
329       return 1;
330     }
331     
332     int result = thisName.compareTo(comparedName);
333     
334     return result;
335   }
336 
337   /**
338    * convenience builder for SkinAddition
339    * does not support the deprecated ValueBinding for translationSource
340    */
341   public static class Builder
342   {
343 
344     public Builder()
345     {
346       _skinFeatures = new SkinFeatures();
347     }
348 
349     public Builder skinId(String skinId)
350     {
351       _skinId = skinId;
352       return this;
353     }
354 
355     public Builder styleSheetName(String styleSheetName)
356     {
357       _styleSheetName = styleSheetName;
358       return this;
359     }
360 
361     public Builder resourceBundleName(String resourceBundleName)
362     {
363       _resourceBundleName = resourceBundleName;
364       return this;
365     }
366 
367     public Builder translationSource(ValueExpression translationSource)
368     {
369       _translationSource = translationSource;
370       return this;
371     }
372 
373     public Builder features(SkinFeatures skinFeatures)
374     {
375       // set only a non null SkinFeatures object
376       if (skinFeatures != null)
377         _skinFeatures = skinFeatures;
378 
379       return this;
380     }
381 
382     public SkinAddition build()
383     {
384       return new SkinAddition(this);
385     }
386 
387     private String       _styleSheetName;
388     private String       _skinId;
389     private String       _resourceBundleName;
390     private ValueExpression _translationSource;
391     private SkinFeatures _skinFeatures;
392   }
393 
394   @Override
395   public boolean equals(Object o)
396   {
397     if (this == o) return true;
398     if (o == null || getClass() != o.getClass()) return false;
399 
400     SkinAddition addition = (SkinAddition) o;
401 
402     if (_resourceBundleName != null ? !_resourceBundleName.equals(addition._resourceBundleName) : addition._resourceBundleName != null)
403       return false;
404     if (_skinFeatures != null ? !_skinFeatures.equals(addition._skinFeatures) : addition._skinFeatures != null)
405       return false;
406     if (_skinId != null ? !_skinId.equals(addition._skinId) : addition._skinId != null)
407       return false;
408     if (_styleSheetName != null ? !_styleSheetName.equals(addition._styleSheetName) : addition._styleSheetName != null)
409       return false;
410     if (_translationSourceVE != null ? !_translationSourceVE.equals(addition._translationSourceVE) : addition._translationSourceVE != null)
411       return false;
412 
413     return true;
414   }
415 
416   @Override
417   public int hashCode()
418   {
419     int result = 17;
420     result = 37 * result + (null == _styleSheetName ? 0 : _styleSheetName.hashCode());
421     result = 37 * result + (null == _skinId ? 0 : _skinId.hashCode());
422     result = 37 * result + (null == _resourceBundleName ? 0 : _resourceBundleName.hashCode());
423     result = 37 * result + (null == _translationSourceVE ? 0 : _translationSourceVE.hashCode());
424     result = 37 * result + (null == _skinFeatures ? 0 : _skinFeatures.hashCode());
425     return result;
426   }
427 
428   /**
429    * Constructor for SkinAddition based on Builder
430    * This constructor can be used to create SkinAddition object for any combination of parameters
431    * @param builder
432    * @See Builder
433    */
434   private SkinAddition (Builder builder)
435   {
436     _skinId = builder._skinId;
437     _styleSheetName = builder._styleSheetName;
438     _resourceBundleName = builder._resourceBundleName;
439     _translationSourceVE = builder._translationSource;
440     _skinFeatures = builder._skinFeatures.getFeatures();
441 
442     // this is deprecated so we do not support this in the new API
443     _translationSourceVB = null;
444 
445   }
446 
447   private final String       _styleSheetName;
448   private final String       _skinId;
449   private final String       _resourceBundleName;
450   private final ValueExpression _translationSourceVE;
451   private final ValueBinding _translationSourceVB;
452   private final Map<String, String> _skinFeatures;
453   
454 }