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  
20  package org.apache.myfaces.tobago.renderkit;
21  
22  import org.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.component.RendererTypes;
24  import org.apache.myfaces.tobago.internal.util.StringUtils;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  import javax.faces.component.UIComponent;
29  import java.util.Locale;
30  
31  public final class LabelWithAccessKey {
32  
33    private static final Logger LOG = LoggerFactory.getLogger(LabelWithAccessKey.class);
34  
35    private String text;
36    private Character accessKey;
37    private int pos = -1;
38    public static final char INDICATOR = '_';
39    public static final String ESCAPED_INDICATOR = "__";
40  
41    public LabelWithAccessKey(String label) {
42      text = label;
43      setup(text);
44    }
45  
46    public LabelWithAccessKey(UIComponent component) {
47      Object value;
48      if (RendererTypes.LABEL.equals(component.getRendererType())) {
49        value = component.getAttributes().get(Attributes.VALUE);
50      } else {
51        value = component.getAttributes().get(Attributes.LABEL);
52      }
53      text = (value == null) ? null : String.valueOf(value);
54      setup(text);
55    }
56  
57    private void findIndicator(String label, int index, int escapedIndicatorCount) {
58      index = label.indexOf(INDICATOR, index);
59      if (index == -1) {
60        text = label;
61      } else if (index == label.length() - 1) {
62        LOG.warn(INDICATOR + " in label is last char, this is not allowed"
63            + "label='" + label + "'.");
64        text = label.substring(0, label.length() - 1);
65        pos = -1;
66      } else if (label.charAt(index + 1) == INDICATOR) {
67        escapedIndicatorCount++;
68        findIndicator(label, index + 2, escapedIndicatorCount);
69      } else {
70        text = label.substring(0, index)
71            + label.substring(index + 1);
72        setAccessKey(text.charAt(index));
73        pos = index - escapedIndicatorCount;
74      }
75    }
76  
77    public void setup(String label) {
78      if (label != null) {
79        findIndicator(label, 0, 0);
80        text = StringUtils.replace(text, ESCAPED_INDICATOR, String.valueOf(INDICATOR));
81      } else {
82        if (accessKey != null && text != null) {
83          pos = text.toLowerCase(Locale.ENGLISH).indexOf(
84              Character.toLowerCase(accessKey.charValue()));
85        }
86      }
87    }
88  
89    public void reset() {
90      text = null;
91      accessKey = null;
92      pos = -1;
93    }
94  
95    public String getText() {
96      return text;
97    }
98  
99    public Character getAccessKey() {
100     return accessKey;
101   }
102 
103   public int getPos() {
104     return pos;
105   }
106 
107   public void setText(String text) {
108     this.text = text;
109   }
110 
111   public void setAccessKey(Character accessKey) {
112     if (!isPermitted(accessKey)) {
113       LOG.warn("Ignoring illegal access key: " + accessKey);
114     }
115     this.accessKey = accessKey;
116   }
117 
118   /**
119    * Ensures, that no illegal character will be write out.
120    * (If this is changed from only allowing letters, the renderers may change the escaping)
121    */
122   private boolean isPermitted(Character accessKey) {
123     return accessKey >= 'a' && accessKey <= 'z' || accessKey >= 'A' && accessKey <= 'Z';
124   }
125 }