src/share/jaxws_classes/com/sun/xml/internal/bind/api/impl/NameConverter.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.bind.api.impl;
27
28 import javax.lang.model.SourceVersion;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.StringTokenizer;
32
33 /**
34 * Converts aribitrary strings into Java identifiers.
35 *
36 * @author
37 * <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
38 */
39 public interface NameConverter
40 {
41 /**
42 * converts a string into an identifier suitable for classes.
43 *
44 * In general, this operation should generate "NamesLikeThis".
45 */
46 String toClassName( String token );
47
48 /**
49 * converts a string into an identifier suitable for interfaces.
50 *
51 * In general, this operation should generate "NamesLikeThis".
52 * But for example, it can prepend every interface with 'I'.
53 */
54 String toInterfaceName( String token );
55
56 /**
57 * converts a string into an identifier suitable for properties.
58 *
59 * In general, this operation should generate "NamesLikeThis",
60 * which will be used with known prefixes like "get" or "set".
61 */
62 String toPropertyName( String token );
63
64 /**
65 * converts a string into an identifier suitable for constants.
66 *
67 * In the standard Java naming convention, this operation should
68 * generate "NAMES_LIKE_THIS".
69 */
70 String toConstantName( String token );
71
72 /**
73 * Converts a string into an identifier suitable for variables.
74 *
75 * In general it should generate "namesLikeThis".
76 */
77 String toVariableName( String token );
78
79 /**
80 * Converts a namespace URI into a package name.
81 * This method should expect strings like
82 * "http://foo.bar.zot/org", "urn:abc:def:ghi" "", or even "###"
83 * (basically anything) and expected to return a package name,
84 * liks "org.acme.foo".
85 *
86 */
87 String toPackageName( String namespaceUri );
88
89 /**
90 * The name converter implemented by Code Model.
91 *
92 * This is the standard name conversion for JAXB.
93 */
94 public static final NameConverter standard = new Standard();
95
96 static class Standard extends NameUtil implements NameConverter {
97 public String toClassName(String s) {
98 return toMixedCaseName(toWordList(s), true);
99 }
100 public String toVariableName(String s) {
101 return toMixedCaseName(toWordList(s), false);
102 }
103 public String toInterfaceName( String token ) {
104 return toClassName(token);
105 }
106 public String toPropertyName(String s) {
107 String prop = toClassName(s);
108 // property name "Class" with collide with Object.getClass,
109 // so escape this.
110 if(prop.equals("Class"))
111 prop = "Clazz";
112 return prop;
113 }
114 public String toConstantName( String token ) {
115 return super.toConstantName(token);
116 }
117 /**
118 * Computes a Java package name from a namespace URI,
119 * as specified in the spec.
120 *
121 * @return
122 * null if it fails to derive a package name.
123 */
124 public String toPackageName( String nsUri ) {
125 // remove scheme and :, if present
126 // spec only requires us to remove 'http' and 'urn'...
127 int idx = nsUri.indexOf(':');
128 String scheme = "";
129 if(idx>=0) {
130 scheme = nsUri.substring(0,idx);
131 if( scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("urn") )
132 nsUri = nsUri.substring(idx+1);
133 }
134
135 // tokenize string
136 ArrayList<String> tokens = tokenize( nsUri, "/: " );
137 if( tokens.size() == 0 ) {
138 return null;
139 }
140
141 // remove trailing file type, if necessary
142 if( tokens.size() > 1 ) {
143 // for uri's like "www.foo.com" and "foo.com", there is no trailing
144 // file, so there's no need to look at the last '.' and substring
145 // otherwise, we loose the "com" (which would be wrong)
146 String lastToken = tokens.get( tokens.size()-1 );
147 idx = lastToken.lastIndexOf( '.' );
148 if( idx > 0 ) {
149 lastToken = lastToken.substring( 0, idx );
150 tokens.set( tokens.size()-1, lastToken );
151 }
152 }
153
154 // tokenize domain name and reverse. Also remove :port if it exists
155 String domain = tokens.get( 0 );
156 idx = domain.indexOf(':');
157 if( idx >= 0) domain = domain.substring(0, idx);
158 ArrayList<String> r = reverse( tokenize( domain, scheme.equals("urn")?".-":"." ) );
159 if( r.get( r.size()-1 ).equalsIgnoreCase( "www" ) ) {
160 // remove leading www
161 r.remove( r.size()-1 );
162 }
163
164 // replace the domain name with tokenized items
165 tokens.addAll( 1, r );
166 tokens.remove( 0 );
167
168 // iterate through the tokens and apply xml->java name algorithm
169 for( int i = 0; i < tokens.size(); i++ ) {
170
171 // get the token and remove illegal chars
172 String token = tokens.get( i );
173 token = removeIllegalIdentifierChars( token );
174
175 // this will check for reserved keywords
176 if (SourceVersion.isKeyword(token.toLowerCase())) {
177 token = '_' + token;
178 }
179
180 tokens.set( i, token.toLowerCase() );
181 }
182
183 // concat all the pieces and return it
184 return combine( tokens, '.' );
185 }
186
187
188 private static String removeIllegalIdentifierChars(String token) {
189 StringBuilder newToken = new StringBuilder(token.length() + 1); // max expected length
190 for( int i = 0; i < token.length(); i++ ) {
191 char c = token.charAt( i );
192 if (i == 0 && !Character.isJavaIdentifierStart(c)) { // c can't be used as FIRST char
193 newToken.append('_');
194 }
195 if (!Character.isJavaIdentifierPart(c)) { // c can't be used
196 newToken.append('_');
197 } else {
198 newToken.append(c); // c is valid
199 }
200 }
201 return newToken.toString();
202 }
203
204
205 private static ArrayList<String> tokenize( String str, String sep ) {
206 StringTokenizer tokens = new StringTokenizer(str,sep);
207 ArrayList<String> r = new ArrayList<String>();
208
209 while(tokens.hasMoreTokens())
210 r.add( tokens.nextToken() );
211
212 return r;
213 }
214
215 private static <T> ArrayList<T> reverse( List<T> a ) {
216 ArrayList<T> r = new ArrayList<T>();
217
218 for( int i=a.size()-1; i>=0; i-- )
219 r.add( a.get(i) );
220
221 return r;
222 }
223
224 private static String combine( List r, char sep ) {
225 StringBuilder buf = new StringBuilder(r.get(0).toString());
226
227 for( int i=1; i<r.size(); i++ ) {
228 buf.append(sep);
229 buf.append(r.get(i));
230 }
231
232 return buf.toString();
233 }
234 }
235
236 /**
237 * JAX-PRC compatible name converter implementation.
238 *
239 * The only difference is that we treat '_' as a valid character
240 * and not as a word separator.
241 */
242 public static final NameConverter jaxrpcCompatible = new Standard() {
243 protected boolean isPunct(char c) {
244 return (c == '.' || c == '-' || c == ';' /*|| c == '_'*/ || c == '\u00b7'
245 || c == '\u0387' || c == '\u06dd' || c == '\u06de');
246 }
247 protected boolean isLetter(char c) {
248 return super.isLetter(c) || c=='_';
249 }
250
251 protected int classify(char c0) {
252 if(c0=='_') return NameUtil.OTHER_LETTER;
253 return super.classify(c0);
254 }
255 };
256
257 /**
258 * Smarter converter used for RELAX NG support.
259 */
260 public static final NameConverter smart = new Standard() {
261 public String toConstantName( String token ) {
262 String name = super.toConstantName(token);
263 if(!SourceVersion.isKeyword(name))
264 return name;
265 else
266 return '_'+name;
267 }
268 };
269 }

mercurial