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.component.html.ext;
20  
21  import javax.faces.FacesException;
22  import java.lang.StringBuffer;
23  
24  class _SubIdConverter
25  {
26      private static final String HEX_CHARSET = "0123456789ABCDEF";
27      
28      /**
29       * Encode the string into an html sub id valid value.  
30       * 
31       * An html id must comply with the following rules
32       * 
33       * 1. Must begin with a letter A-Z or a-z
34       * 2. Can be followed by: letters (A-Za-z), digits (0-9), hyphens ("-"), underscores ("_"), colons (":"), and periods (".")
35       * 3. Values are case-sensitive
36       * 
37       * The first rule is warranted because this convert an sub id, so a prefix is always added to
38       * the returning string. The encoder converts all non valid chars into a unicode hex string prefixed with '_' char.
39       * For example _ is converted to _005F, + is converted to _002B and so on.
40       * 
41       * @param string
42       * @param characterEncoding
43       * @return
44       */
45      public static String encode(final String string)
46      {
47          StringBuffer sb = null;    //create later on demand
48          String app;
49          char c;
50          boolean endLoop = false;
51          for (int i = 0; i < string.length (); ++i)
52          {
53              app = null;
54              c = string.charAt(i);
55              
56              if (( c >= '0' && c <='9') || (c >='A' && c <='Z') || (c >='a' && c <='z')
57                  || c == ':' || c == '.' ) //|| c == '-' // '-' used to indicate rowIndex
58              {
59                  //No encoding, just do nothing, char will be added later.
60              }
61              else
62              {
63                  
64                  app = "_" + HEX_CHARSET.charAt( ((c >> 0x0C) % 0x10)) +  HEX_CHARSET.charAt( ((c >> 0x8) % 0x10)) + HEX_CHARSET.charAt( ((c >> 0x4) % 0x10)) +HEX_CHARSET.charAt(c % 0x10);
65              }
66                          
67              if (app != null)
68              {
69                  if (sb == null)
70                  {
71                      sb = new StringBuffer(string.substring(0, i));
72                  }
73                  sb.append(app);
74              } else {
75                  if (sb != null)
76                  {
77                      sb.append(c);
78                  }
79              }
80              if (endLoop)
81              {
82                  break;
83              }
84          }
85          if (sb == null)
86          {
87              return string;
88          }
89          else
90          {
91              return sb.toString();
92          }
93      }
94  
95      public static String decode(final String string)
96      {
97          StringBuffer sb = null;    //create later on demand
98          String app;
99          char c;
100         boolean endLoop = false;
101         for (int i = 0; i < string.length (); ++i)
102         {
103             app = null;
104             c = string.charAt(i);
105             
106             if (c == '_')
107             {
108                 int value = (toDigit(string.charAt(i+1)) << 0x0C) + (toDigit(string.charAt(i+2)) << 0x08) + (toDigit(string.charAt(i+3)) << 0x04) + toDigit(string.charAt(i+4));
109                 
110                 if (sb == null)
111                 {
112                     sb = new StringBuffer(string.substring(0, i));
113                 }
114                 i += 4;
115                 app = ""+((char)value);
116             }
117             else
118             {
119                 //No decoding
120             }
121 
122             if (app != null)
123             {
124                 if (sb == null)
125                 {
126                     sb = new StringBuffer(string.substring(0, i));
127                 }
128                 sb.append(app);
129             } else {
130                 if (sb != null)
131                 {
132                     sb.append(c);
133                 }
134             }
135             if (endLoop)
136             {
137                 break;
138             }
139         }
140         if (sb == null)
141         {
142             return string;
143         }
144         else
145         {
146             return sb.toString();
147         }
148     }
149     
150     /**
151      * Converts a hexadecimal character to an integer.
152      * 
153      * @param ch
154      *            A character to convert to an integer digit
155      * @param index
156      *            The index of the character in the source
157      * @return An integer
158      * @throws DecoderException
159      *             Thrown if ch is an illegal hex character
160      */
161     protected static int toDigit(char ch)
162     {
163         int digit = Character.digit(ch, 16);
164         if (digit == -1)
165         {
166             throw new FacesException("Illegal hexadecimal charcter ");
167         }
168         return digit;
169     }
170 }