View Javadoc

1   /*
2    * Copyright 2002-2009 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package net.sf.json.util;
18  
19  import net.sf.json.JSONException;
20  
21  import org.apache.commons.lang.StringUtils;
22  
23  /**
24   * Transforms a string into a valid Java identifier.<br>
25   * There are five predefined strategies:
26   * <ul>
27   * <li>NOOP: does not perform transformation.</li>
28   * <li>CAMEL_CASE: follows the camel case convention, deletes non
29   * JavaIndentifierPart chars.</li>
30   * <li>UNDERSCORE: transform whitespace and non JavaIdentifierPart chars to
31   * '_'.</li>
32   * <li>WHITESPACE: deletes whitespace and non JavaIdentifierPart chars.</li>
33   * <li>STRICT: always throws a JSONException, does not perform transformation.</li>
34   * </ul>
35   * 
36   * @author Andres Almiray <aalmiray@users.sourceforge.net>
37   */
38  public abstract class JavaIdentifierTransformer {
39     /** CamelCase transformer 'camel case' => 'camelCase' */
40     public static final JavaIdentifierTransformer CAMEL_CASE = new CamelCaseJavaIdentifierTransformer();
41     /** Noop transformer '@invalid' => '@invalid' */
42     public static final JavaIdentifierTransformer NOOP = new NoopJavaIdentifierTransformer();
43     /** Strict transformer '@invalid' => JSONException */
44     public static final JavaIdentifierTransformer STRICT = new StrictJavaIdentifierTransformer();
45     /** Underscore transformer 'under score' => 'under_score' */
46     public static final JavaIdentifierTransformer UNDERSCORE = new UnderscoreJavaIdentifierTransformer();
47     /** Whitespace transformer 'white space' => 'whitespace' */
48     public static final JavaIdentifierTransformer WHITESPACE = new WhiteSpaceJavaIdentifierTransformer();
49  
50     public abstract String transformToJavaIdentifier( String str );
51  
52     /**
53      * Removes all non JavaIdentifier chars from the start of the string.
54      * 
55      * @throws JSONException if the resulting string has zero length.
56      */
57     protected final String shaveOffNonJavaIdentifierStartChars( String str ) {
58        String str2 = str;
59        // shave off first char if not valid
60        boolean ready = false;
61        while( !ready ){
62           if( !Character.isJavaIdentifierStart( str2.charAt( 0 ) ) ){
63              str2 = str2.substring( 1 );
64              if( str2.length() == 0 ){
65                 throw new JSONException( "Can't convert '" + str + "' to a valid Java identifier" );
66              }
67           }else{
68              ready = true;
69           }
70        }
71        return str2;
72     }
73  
74     private static final class CamelCaseJavaIdentifierTransformer extends JavaIdentifierTransformer {
75        public String transformToJavaIdentifier( String str ) {
76           if( str == null ){
77              return null;
78           }
79  
80           String str2 = shaveOffNonJavaIdentifierStartChars( str );
81  
82           char[] chars = str2.toCharArray();
83           int pos = 0;
84           StringBuffer buf = new StringBuffer();
85           boolean toUpperCaseNextChar = false;
86           while( pos < chars.length ){
87              if( !Character.isJavaIdentifierPart( chars[pos] )
88                    || Character.isWhitespace( chars[pos] ) ){
89                 toUpperCaseNextChar = true;
90              }else{
91                 if( toUpperCaseNextChar ){
92                    buf.append( Character.toUpperCase( chars[pos] ) );
93                    toUpperCaseNextChar = false;
94                 }else{
95                    buf.append( chars[pos] );
96                 }
97              }
98              pos++;
99           }
100          return buf.toString();
101       }
102    }
103 
104    private static final class NoopJavaIdentifierTransformer extends JavaIdentifierTransformer {
105       public String transformToJavaIdentifier( String str ) {
106          return str;
107       }
108    }
109 
110    private static final class StrictJavaIdentifierTransformer extends JavaIdentifierTransformer {
111       public String transformToJavaIdentifier( String str ) {
112          throw new JSONException( "'" + str + "' is not a valid Java identifier." );
113       }
114    }
115    private static final class UnderscoreJavaIdentifierTransformer extends JavaIdentifierTransformer {
116       public String transformToJavaIdentifier( String str ) {
117          if( str == null ){
118             return null;
119          }
120          String str2 = shaveOffNonJavaIdentifierStartChars( str );
121 
122          char[] chars = str2.toCharArray();
123          int pos = 0;
124          StringBuffer buf = new StringBuffer();
125          boolean toUnderScorePreviousChar = false;
126          while( pos < chars.length ){
127             if( !Character.isJavaIdentifierPart( chars[pos] )
128                   || Character.isWhitespace( chars[pos] ) ){
129                toUnderScorePreviousChar = true;
130             }else{
131                if( toUnderScorePreviousChar ){
132                   buf.append( "_" );
133                   toUnderScorePreviousChar = false;
134                }
135                buf.append( chars[pos] );
136             }
137             pos++;
138          }
139          if( buf.charAt( buf.length() - 1 ) == '_' ){
140             buf.deleteCharAt( buf.length() - 1 );
141          }
142          return buf.toString();
143       }
144    }
145    private static final class WhiteSpaceJavaIdentifierTransformer extends JavaIdentifierTransformer {
146       public String transformToJavaIdentifier( String str ) {
147          if( str == null ){
148             return null;
149          }
150          String str2 = shaveOffNonJavaIdentifierStartChars( str );
151          str2 = StringUtils.deleteWhitespace( str2 );
152          char[] chars = str2.toCharArray();
153          int pos = 0;
154          StringBuffer buf = new StringBuffer();
155          while( pos < chars.length ){
156             if( Character.isJavaIdentifierPart( chars[pos] ) ){
157                buf.append( chars[pos] );
158             }
159             pos++;
160          }
161          return buf.toString();
162       }
163    }
164 }