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.menu;
20  
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.el.ELContext;
25  import javax.el.ExpressionFactory;
26  import javax.el.MethodExpression;
27  import javax.faces.context.FacesContext;
28  import javax.faces.event.ActionEvent;
29  
30  import org.apache.myfaces.trinidad.util.ContainerUtils;
31  
32  /**
33   * This class is a thread safe version of ItemNode class.
34   * It replicates most of the code in ItemNode but makes
35   * sure it does not modify state of the object.
36   * 
37   * Therefore multiple request threads can access the
38   * properties of the objects of this class,in a thread safe
39   * manner.
40   * 
41   * Please note that setters should not be called on objects
42   * of this class.Objects of this class are fully initialized
43   * on construction.
44   *
45   */
46  public class ImmutableItemNode extends ItemNode
47  {
48    
49    public ImmutableItemNode(ItemNode node)
50    {
51      _icon = node.getIconProperty();
52      _focusViewId = node.getFocusViewIdProperty();
53      _renderedStr = node.getRenderedProperty();
54      _disabledStr = node.getDisabledProperty();
55      _visibleStr = node.getVisibleProperty();
56      _readOnlyStr = node.getReadOnlyProperty();
57      _handlerId = node.getHandlerIdProperty();
58      _bundleKey = node.getBundleKeyProperty();
59      _bundleName = node.getBundleNameProperty();
60      _accessKey = node.getAccessKeyProperty();
61      _id = node.getIdProperty();
62      _modelId = node.getModelIdProperty();
63      _uniqueId = node.getUniqueIdProperty();
64      _labelAndAccessKey = node.getLabelAndAccessKeyProperty();
65      _defaultFocusPathStr = node.getDefaultFocusPathProperty();
66  
67      // Root Menu model's Request Map Key
68      _rootModelKey = node.getRootModelKeyProperty();
69  
70      _rootId = node.getRootIdProperty();
71  
72      _customPropList = node.getCustomPropListProperty();
73  
74      _destination = node.getDestinationProperty();
75      _targetFrame = node.getTargetFrameProperty();
76      _action = node.getActionProperty();
77      _actionListener = node.getActionListenerProperty();
78      _launchListener = node.getLaunchListenerProperty();
79      _returnListener = node.getReturnListenerProperty();
80      _immediateStr = node.getImmediateProperty();
81      _useWindowStr = node.getUseWindowProperty();
82      _windowHeightStr = node.getWindowHeightProperty();
83      _windowWidthStr = node.getWindowWidthProperty();
84  
85      _label = node.getLabelProperty();
86    }
87  
88    public final Map<String, String> getCustomPropList()
89    {
90      return _customPropList;
91    }
92  
93    public final String getDestination()
94    {
95  
96      String value = _destination;
97  
98      // Could be EL expression
99      if (value != null && ContainerUtils.isValueReference(value))
100     {
101       // Value of action is EL method binding, so we
102       // need to evaluate it
103       value = MenuUtils.getBoundValue(value, String.class);
104     }
105 
106     // Appending nodeId to URL so that we can identify the node
107     // when getFocusRowKey() is called on the model.
108     return value != null ? value + "?nodeId=" + getUniqueId() : value;
109 
110   }
111 
112   public final String getTargetFrame()
113   {
114     String value = _targetFrame;
115 
116     // Could be EL expression
117     if (value != null && ContainerUtils.isValueReference(value))
118     {
119       // Value of destination is EL value binding, so we
120       // need to evaluate it
121       value = MenuUtils.getBoundValue(value, String.class);
122     }
123 
124     return value;
125   }
126 
127   public final String getActionListener()
128   {
129     String value = _actionListener;
130 
131     // Could be EL expression
132     if (value != null && ContainerUtils.isValueReference(value))
133     {
134       // Value of action is EL method binding, so we
135       // need to evaluate it
136       value = MenuUtils.getBoundValue(value, String.class);
137     }
138 
139     return value;
140   }
141 
142   public final String getLaunchListener()
143   {
144 
145     String value = _launchListener;
146 
147     // Could be EL expression
148     if (value != null && ContainerUtils.isValueReference(value))
149     {
150       // Value of action is EL method binding, so we
151       // need to evaluate it
152       value = MenuUtils.getBoundValue(value, String.class);
153     }
154 
155     return value;
156   }
157 
158   public final String getReturnListener()
159   {
160     String value = _returnListener;
161 
162     // Could be EL expression
163     if (value != null && ContainerUtils.isValueReference(value))
164     {
165       // Value of action is EL method binding, so we
166       // need to evaluate it
167       value = MenuUtils.getBoundValue(value, String.class);
168     }
169 
170     return value;
171 
172   }
173 
174   public final boolean getImmediate()
175   {
176     boolean immediate = MenuUtils.evalBoolean(_immediateStr, false);
177     return immediate;
178   }
179 
180   public final boolean getUseWindow()
181   {
182     boolean useWindow = MenuUtils.evalBoolean(_useWindowStr, false);
183     return useWindow;
184   }
185 
186   public final int getWindowHeight()
187   {
188     int windowHeight = MenuUtils.evalInt(_windowHeightStr);
189     return windowHeight;
190   }
191 
192   public final int getWindowWidth()
193   {
194     int windowWidth = MenuUtils.evalInt(_windowWidthStr);
195     return windowWidth;
196   }
197 
198   public final String getLabel()
199   {
200     if (_bundleKey != null && _bundleName != null)
201     {
202       // Load the resource bundle based on the locale of the
203       // current request. If the locale has not changed, this
204       // method just returns.
205       MenuUtils.loadBundle(_bundleName, _bundleKey + getHandlerId());
206     }
207 
208     if (_label != null && ContainerUtils.isValueReference(_label))
209     {
210       // do not set _label to the evaluated EL.
211       // It may change at times in the EL.
212       return _evalElStr(_label);
213     }
214     if (_label == null && _labelAndAccessKey != null)
215     {
216       int ampIdx = 0;
217       String labelAndAccessKeyEval = null;
218       String labelAndAccessKey = _labelAndAccessKey;
219       String label;
220       if (ContainerUtils.isValueReference(labelAndAccessKey))
221       {
222         labelAndAccessKeyEval = _evalElStr(labelAndAccessKey);
223       } else
224       {
225         labelAndAccessKeyEval = labelAndAccessKey;
226       }
227 
228       String accessKey;
229       if (labelAndAccessKeyEval == null ||
230           (ampIdx = labelAndAccessKeyEval.indexOf('&')) == -1)
231       {
232         // String is null or a label w/o an accesskey
233         label = labelAndAccessKeyEval;
234       } else if (ampIdx == (labelAndAccessKeyEval.length() - 1))
235       {
236         // & is last character, strip it.
237         label = labelAndAccessKeyEval.substring(0, ampIdx);
238       } else
239       {
240         // We have a string with an accessKey somewhere
241         char[] keyArray = labelAndAccessKeyEval.toCharArray();
242         int len = labelAndAccessKeyEval.length();
243         char[] keyArray2 = new char[len];
244         int i, j = 0;
245         boolean accessKeyFound = false;
246 
247         for (i = 0, j = 0; i < len; i++, j++)
248         {
249           if (keyArray[i] == '&')
250           {
251             i++;
252 
253             if (!accessKeyFound && keyArray[i] != '&')
254             {
255               // We have our accessKey
256               accessKey = labelAndAccessKeyEval.substring(i, i + 1);
257               accessKeyFound = true;
258             }
259           }
260 
261           keyArray2[j] = keyArray[i];
262         }
263 
264         String label1 = new String(keyArray2, 0, j);
265         label = label1;
266       }
267       return label;
268 
269     }
270     return _label;
271   }
272 
273   public final String getIcon()
274   {
275     return MenuUtils.evalString(_icon);
276   }
277 
278   public final List<MenuNode> getChildren()
279   {
280     return _children;
281   }
282 
283   public void setChildren(List<MenuNode> children)
284   {
285     _children = children;
286   }
287 
288   public final String getFocusViewId()
289   {
290     return _focusViewId;
291   }
292 
293   public final boolean getRendered()
294   {
295     boolean rendered = MenuUtils.evalBoolean(_renderedStr, true);
296     return rendered;
297   }
298 
299   public final boolean getDisabled()
300   {
301     boolean disabled = MenuUtils.evalBoolean(_disabledStr, false);
302     return disabled;
303   }
304 
305   public final boolean getVisible()
306   {
307     boolean visible = MenuUtils.evalBoolean(_visibleStr, true);
308     return visible;
309   }
310 
311   public final boolean getReadOnly()
312   {
313     boolean readOnly = MenuUtils.evalBoolean(_readOnlyStr, false);
314     return readOnly;
315   }
316 
317   protected final String getHandlerId()
318   {
319     return _handlerId;
320   }
321 
322   public final String getBundleKey()
323   {
324     return _bundleKey;
325   }
326 
327   public final String getBundleName()
328   {
329     return _bundleName;
330   }
331 
332   public void actionListener(ActionEvent event)
333   {
334     String value = _actionListener;
335     if (value != null)
336     {
337       FacesContext facesContext = FacesContext.getCurrentInstance();
338       ExpressionFactory expressionFactory =
339           facesContext.getApplication().getExpressionFactory();
340       ELContext context = facesContext.getELContext();
341 
342       MethodExpression methodExpression =
343           expressionFactory.createMethodExpression(context, value, Void.TYPE,
344               new Class<?>[]
345               { ActionEvent.class });
346       methodExpression.invoke(context, new Object[]
347       { event });
348     }
349 
350   }
351 
352   public String doAction()
353   {
354     String value = _action;
355 
356     if (value != null)
357     {
358       FacesContext facesContext = FacesContext.getCurrentInstance();
359       ExpressionFactory expressionFactory =
360           facesContext.getApplication().getExpressionFactory();
361       ELContext context = facesContext.getELContext();
362       MethodExpression methodExpression =
363           expressionFactory.createMethodExpression(context, value,
364               String.class, new Class<?>[]
365               {});
366       value = (String) methodExpression.invoke(context, null);
367     }
368 
369     // Post me as the selected Node for the request
370     postSelectedNode(this);
371 
372     return value;
373   }
374 
375   public final char getAccessKey()
376   {
377     if (_accessKey == null && _labelAndAccessKey != null)
378     {
379       int ampIdx = 0;
380       String labelAndAccessKeyEval = null;
381       String labelAndAccessKey = _labelAndAccessKey;
382       String label;
383       if (ContainerUtils.isValueReference(labelAndAccessKey))
384       {
385         labelAndAccessKeyEval = _evalElStr(labelAndAccessKey);
386       } 
387       else
388       {
389         labelAndAccessKeyEval = labelAndAccessKey;
390       }
391 
392       String accessKey = null;
393       if (labelAndAccessKeyEval == null ||
394           (ampIdx = labelAndAccessKeyEval.indexOf('&')) == -1)
395       {
396         // String is null or a label w/o an accesskey
397         label = labelAndAccessKeyEval;
398       } else if (ampIdx == (labelAndAccessKeyEval.length() - 1))
399       {
400         // & is last character, strip it.
401         label = labelAndAccessKeyEval.substring(0, ampIdx);
402       } else
403       {
404         // We have a string with an accessKey somewhere
405         char[] keyArray = labelAndAccessKeyEval.toCharArray();
406         int len = labelAndAccessKeyEval.length();
407         char[] keyArray2 = new char[len];
408         int i, j = 0;
409         boolean accessKeyFound = false;
410 
411         for (i = 0, j = 0; i < len; i++, j++)
412         {
413           if (keyArray[i] == '&')
414           {
415             i++;
416 
417             if (!accessKeyFound && keyArray[i] != '&')
418             {
419               // We have our accessKey
420               accessKey = labelAndAccessKeyEval.substring(i, i + 1);
421               accessKeyFound = true;
422             }
423           }
424 
425           keyArray2[j] = keyArray[i];
426         }
427 
428         String label1 = new String(keyArray2, 0, j);
429         label = label1;
430       }
431       return (accessKey != null)? accessKey.charAt(0):'\0';
432 
433     }
434     else 
435     {
436       String accessKeyStr = MenuUtils.evalString(_accessKey);
437       if (accessKeyStr == null || accessKeyStr.length() > 1)
438         return '\0';
439       return accessKeyStr.charAt(0);
440     }
441     
442   }
443 
444   public final String getId()
445   {
446     return _id;
447   }
448 
449   public final String getModelId()
450   {
451     return _modelId;
452   }
453 
454   public final String getUniqueId()
455   {
456     return _uniqueId;
457   }
458   
459   public final String getLabelAndAccessKey()
460   {
461     String labelAndAcessKeyEval;
462     if (_labelAndAccessKey != null)
463     {
464       int ampIdx = 0;
465       String labelAndAccessKeyEval = null;
466       String labelAndAccessKey = _labelAndAccessKey;
467       String label;
468       if (_bundleKey != null && _bundleName != null)
469       {
470         // Load the resource bundle based on the locale of the
471         // current request. If the locale has not changed, this
472         // method just returns.
473         MenuUtils.loadBundle(_bundleName, _bundleKey + getHandlerId());
474       }
475       if (ContainerUtils.isValueReference(labelAndAccessKey))
476       {
477         labelAndAccessKeyEval = _evalElStr(labelAndAccessKey);
478       } else
479       {
480         labelAndAccessKeyEval = labelAndAccessKey;
481       }
482 
483       String accessKey = null;
484       if (labelAndAccessKeyEval == null ||
485           (ampIdx = labelAndAccessKeyEval.indexOf('&')) == -1)
486       {
487         // String is null or a label w/o an accesskey
488         label = labelAndAccessKeyEval;
489       } else if (ampIdx == (labelAndAccessKeyEval.length() - 1))
490       {
491         // & is last character, strip it.
492         label = labelAndAccessKeyEval.substring(0, ampIdx);
493       } else
494       {
495         // We have a string with an accessKey somewhere
496         char[] keyArray = labelAndAccessKeyEval.toCharArray();
497         int len = labelAndAccessKeyEval.length();
498         char[] keyArray2 = new char[len];
499         int i, j = 0;
500         boolean accessKeyFound = false;
501 
502         for (i = 0, j = 0; i < len; i++, j++)
503         {
504           if (keyArray[i] == '&')
505           {
506             i++;
507 
508             if (!accessKeyFound && keyArray[i] != '&')
509             {
510               // We have our accessKey
511               accessKey = labelAndAccessKeyEval.substring(i, i + 1);
512               accessKeyFound = true;
513             }
514           }
515 
516           keyArray2[j] = keyArray[i];
517         }
518 
519         String label1 = new String(keyArray2, 0, j);
520         label = label1;
521       }
522       // https://issues.apache.org/jira/browse/TRINIDAD-1588
523       if (accessKey == null) {
524           return label;
525       }
526       return _joinLabelAndAccessKey(label, accessKey);
527     }
528     return null;
529   }
530 
531   public final boolean getDefaultFocusPath()
532   {
533     boolean defaultFocusPath =
534         MenuUtils.evalBoolean(_defaultFocusPathStr, false);
535     return defaultFocusPath;
536   }
537 
538   public final String getRootModelKey()
539   {
540     return _rootModelKey;
541   }
542 
543   public final int getRootId()
544   {
545     return _rootId;
546   }
547 
548   private String _evalElStr(String str)
549   {
550     if (str == null)
551       return null;
552 
553     String keystr =
554         MenuUtils.stringReplaceFirst(str.trim(), _bundleKey, _bundleKey +
555             getHandlerId());
556     String elVal = MenuUtils.getBoundValue(keystr, String.class);
557     return elVal;
558   }
559 
560   private String _joinLabelAndAccessKey(String label, String accessKey)
561   {
562     char[] keyArray = label.toCharArray();
563     int len = label.length();
564     int lentimes2 = len * 2;
565     char[] keyArray2 = new char[lentimes2];
566     int i, j = 0;
567     boolean accessKeyFound = false;
568 
569     // find the first occurrence of a single Ampersand
570     for (i = 0, j = 0; i < len; i++, j++)
571     {
572       // AccessKey
573       if (keyArray[i] == accessKey.charAt(0) && !accessKeyFound)
574       {
575         keyArray2[j] = '&';
576         j++;
577         accessKeyFound = true;
578       }
579 
580       keyArray2[j] = keyArray[i];
581 
582       // Ampersand as regular character
583       // double it up.
584       if (keyArray[i] == '&')
585       {
586         j++;
587         keyArray2[j] = keyArray[i];
588       }
589     }
590 
591     String combinedLabel = new String(keyArray2, 0, j);
592     return combinedLabel;
593   }
594 
595   private final String _icon;
596   private List<MenuNode> _children = null;
597   private final String _focusViewId;
598   private final String _renderedStr;
599   private final String _disabledStr;
600   private final String _visibleStr;
601   private final String _readOnlyStr;
602   private final String _handlerId;
603   private final String _bundleKey;
604   private final String _bundleName;
605   private final String _accessKey;
606   private final String _id;
607   private final String _modelId;
608   private final String _labelAndAccessKey;
609   private final String _defaultFocusPathStr;
610   private final String _uniqueId;
611 
612   // Root Menu model's Request Map Key
613   private final String _rootModelKey;
614 
615   private final int _rootId;
616 
617   private final Map<String, String> _customPropList;
618 
619   private final String _destination;
620   private final String _targetFrame;
621   private final String _action;
622   private final String _actionListener;
623   private final String _launchListener;
624   private final String _returnListener;
625   private final String _immediateStr;
626   private final String _useWindowStr;
627   private final String _windowHeightStr;
628   private final String _windowWidthStr;
629 
630   private final String _label;
631 
632 }