001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.myfaces.tobago.renderkit;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    import org.apache.commons.lang.StringUtils;
025    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_LABEL;
026    import static org.apache.myfaces.tobago.TobagoConstants.ATTR_VALUE;
027    import static org.apache.myfaces.tobago.TobagoConstants.RENDERER_TYPE_LABEL;
028    
029    import javax.faces.component.UIComponent;
030    import java.util.Locale;
031    
032    public final class LabelWithAccessKey {
033    
034      private static final Log LOG = LogFactory.getLog(LabelWithAccessKey.class);
035    
036      private String text;
037      private Character accessKey;
038      private int pos = -1;
039      public static final char INDICATOR = '_';
040      public static final String ESCAPED_INDICATOR = "__";
041    
042      public LabelWithAccessKey(UIComponent component) {
043        Object value;
044        if (RENDERER_TYPE_LABEL.equals(component.getRendererType())) {
045          value = component.getAttributes().get(ATTR_VALUE);
046        } else {
047          value = component.getAttributes().get(ATTR_LABEL);
048        }
049        text = (value == null) ? null : String.valueOf(value);
050        setup(text);
051      }
052    
053      private void findIndicator(String label, int index, int escapedIndicatorCount) {
054        index = label.indexOf(INDICATOR, index);
055        if (index == -1) {
056          text = label;
057        } else if (index == label.length() - 1) {
058          LOG.warn(INDICATOR + " in label is last char, this is not allowed"
059              + "label='" + label + "'.");
060          text = label.substring(0, label.length() - 1);
061          pos = -1;
062        } else if (label.charAt(index + 1) == INDICATOR) {
063          escapedIndicatorCount++;
064          findIndicator(label, index + 2, escapedIndicatorCount);
065        } else {
066          text = label.substring(0, index)
067              + label.substring(index + 1);
068          accessKey = text.charAt(index);
069          pos = index - escapedIndicatorCount;
070        }
071      }
072    
073      public void setup(String label) {
074        if (label != null) {
075          findIndicator(label, 0, 0);
076          text = StringUtils.replace(text, ESCAPED_INDICATOR, String.valueOf(INDICATOR));
077        } else {
078          if (accessKey != null && text != null) {
079            pos = text.toLowerCase(Locale.ENGLISH).indexOf(
080                Character.toLowerCase(accessKey.charValue()));
081          }
082        }
083      }
084    
085      public void reset() {
086        text = null;
087        accessKey = null;
088        pos = -1;
089      }
090    
091      public String getText() {
092        return text;
093      }
094    
095      public Character getAccessKey() {
096        return accessKey;
097      }
098    
099      public int getPos() {
100        return pos;
101      }
102    
103      public void setText(String text) {
104        this.text = text;
105      }
106    
107      public void setAccessKey(Character accessKey) {
108        this.accessKey = accessKey;
109      }
110    
111    }