| 1 package org.objectweb.celtix.jaxb; 2 3 import java.lang.reflect.Method ; 4 import java.net.URI ; 5 import java.net.URISyntaxException ; 6 7 import java.util.ArrayList ; 8 import java.util.Arrays ; 9 import java.util.HashMap ; 10 import java.util.HashSet ; 11 import java.util.List ; 12 import java.util.Map ; 13 import java.util.Set ; 14 import java.util.StringTokenizer ; 15 import java.util.concurrent.Future ; 16 17 import javax.xml.ws.AsyncHandler; 18 import javax.xml.ws.Response; 19 20 public final class JAXBUtils { 21 22 public enum IdentifierType { 23 CLASS, 24 INTERFACE, 25 GETTER, 26 SETTER, 27 VARIABLE, 28 CONSTANT 29 }; 30 31 public static final String JAXB_URI = "http://java.sun.com/xml/ns/jaxb"; 32 33 private static final Set <String > KEYWORDS = new HashSet <String >(Arrays.asList( 34 "abstract", "continue", "for", "new", "switch", 35 "assert", "default", "if", "package", "synchronized", 36 "boolean", "do", "goto", "private", "this", 37 "break", "double", "implements", "protected", "throw", 38 "byte", "else", "import", "public", "throws", 39 "case", "enum", "instanceof", "return", "transient", 40 "catch", "extends", "int", "short", "try", 41 "char", "final", "interface", "static", "void", 42 "class", "finally", "long", "strictfp", "volatile", 43 "const", "float", "native", "super", "while" 44 )); 45 46 private static final char[] XML_NAME_PUNCTUATION_CHARS = new char[] { 47 '\u002D', 48 '\u002E', 49 '\u003A', 50 '\u00B7', 51 '\u0387', 52 '\u06DD', 53 '\u06DE', 54 '\u005F', 55 }; 56 57 private static final String XML_NAME_PUNCTUATION_STRING = new String (XML_NAME_PUNCTUATION_CHARS); 58 59 private static final Map <String , String > BUILTIN_DATATYPES_MAP; 60 private static final Map <String , Class > HOLDER_TYPES_MAP; 61 62 static { 63 BUILTIN_DATATYPES_MAP = new HashMap <String , String >(); 64 BUILTIN_DATATYPES_MAP.put("string", "java.lang.String"); 65 BUILTIN_DATATYPES_MAP.put("integer", "java.math.BigInteger"); 66 BUILTIN_DATATYPES_MAP.put("int", "int"); 67 BUILTIN_DATATYPES_MAP.put("long", "long"); 68 BUILTIN_DATATYPES_MAP.put("short", "short"); 69 BUILTIN_DATATYPES_MAP.put("decimal", "java.math.BigDecimal"); 70 BUILTIN_DATATYPES_MAP.put("float", "float"); 71 BUILTIN_DATATYPES_MAP.put("double", "double"); 72 BUILTIN_DATATYPES_MAP.put("boolean", "boolean"); 73 BUILTIN_DATATYPES_MAP.put("byte", "byte"); 74 BUILTIN_DATATYPES_MAP.put("QName", "javax.xml.namespace.QName"); 75 BUILTIN_DATATYPES_MAP.put("dateTime", "javax.xml.datatype.XMLGregorianCalendar"); 76 BUILTIN_DATATYPES_MAP.put("base64Binary", "byte[]"); 77 BUILTIN_DATATYPES_MAP.put("hexBinary", "byte[]"); 78 BUILTIN_DATATYPES_MAP.put("unsignedInt", "long"); 79 BUILTIN_DATATYPES_MAP.put("unsignedShort", "short"); 80 BUILTIN_DATATYPES_MAP.put("unsignedByte", "byte"); 81 BUILTIN_DATATYPES_MAP.put("time", "javax.xml.datatype.XMLGregorianCalendar"); 82 BUILTIN_DATATYPES_MAP.put("date", "javax.xml.datatype.XMLGregorianCalendar"); 83 BUILTIN_DATATYPES_MAP.put("gYear", "javax.xml.datatype.XMLGregorianCalendar"); 84 BUILTIN_DATATYPES_MAP.put("gYearMonth", "javax.xml.datatype.XMLGregorianCalendar"); 85 BUILTIN_DATATYPES_MAP.put("gMonth", "javax.xml.datatype.XMLGregorianCalendar"); 86 BUILTIN_DATATYPES_MAP.put("gMonthDay", "javax.xml.datatype.XMLGregorianCalendar"); 87 BUILTIN_DATATYPES_MAP.put("gDay", "javax.xml.datatype.XMLGregorianCalendar"); 88 BUILTIN_DATATYPES_MAP.put("duration", "javax.xml.datatype.Duration"); 89 BUILTIN_DATATYPES_MAP.put("NOTATION", "javax.xml.namespace.QName"); 90 BUILTIN_DATATYPES_MAP.put("string", "java.lang.String"); 91 92 HOLDER_TYPES_MAP = new HashMap <String , Class >(); 93 HOLDER_TYPES_MAP.put("int", java.lang.Integer .class); 94 HOLDER_TYPES_MAP.put("long", java.lang.Long .class); 95 HOLDER_TYPES_MAP.put("short", java.lang.Short .class); 96 HOLDER_TYPES_MAP.put("float", java.lang.Float .class); 97 HOLDER_TYPES_MAP.put("double", java.lang.Double .class); 98 HOLDER_TYPES_MAP.put("boolean", java.lang.Boolean .class); 99 HOLDER_TYPES_MAP.put("byte", java.lang.Byte .class); 100 } 101 102 103 107 private JAXBUtils() { 108 } 109 110 public static String builtInTypeToJavaType(String type) { 111 return BUILTIN_DATATYPES_MAP.get(type); 112 } 113 114 public static Class holderClass(String type) { 115 return HOLDER_TYPES_MAP.get(type); 116 } 117 118 124 public static boolean isJavaKeyword(String word) { 125 return KEYWORDS.contains(word); 126 } 127 128 135 public static String namespaceURIToPackage(String namespaceURI) { 136 try { 137 return nameSpaceURIToPackage(new URI (namespaceURI)); 138 } catch (URISyntaxException ex) { 139 return null; 140 } 141 } 142 143 150 public static String nameSpaceURIToPackage(URI uri) { 151 152 StringBuffer packageName = new StringBuffer (); 153 154 String authority = uri.getAuthority(); 155 156 157 if (null != authority && !"".equals(authority)) { 158 if ("urn".equals(uri.getScheme())) { 159 packageName.append(authority); 160 for (int i = 0; i < packageName.length(); i++) { 161 if (packageName.charAt(i) == '-') { 162 packageName.setCharAt(i, '.'); 163 } 164 } 165 authority = packageName.toString(); 166 packageName.setLength(0); 167 } 168 169 StringTokenizer st = new StringTokenizer (authority, "."); 170 if (st.hasMoreTokens()) { 171 String token = null; 172 while (st.hasMoreTokens()) { 173 token = st.nextToken(); 174 if (packageName.length() == 0) { 175 if ("www".equals(token)) { 176 continue; 177 } 178 } else { 179 packageName.insert(0, "."); 180 } 181 packageName.insert(0, token); 182 } 183 184 if (!("com".equals(token) || "gov".equals(token) || "net".equals(token) 185 || "org".equals(token) || "edu".equals(token))) { 186 packageName.setLength(0); 187 188 } 189 } 190 } 191 192 String path = uri.getPath(); 193 int index = path.lastIndexOf('.'); 194 if (index < 0) { 195 index = path.length(); 196 } 197 StringTokenizer st = new StringTokenizer (path.substring(0, index), "/"); 198 while (st.hasMoreTokens()) { 199 String token = st.nextToken(); 200 if (packageName.length() > 0) { 201 packageName.append('.'); 202 } 203 packageName.append(normalizePackageNamePart(token)); 204 } 205 return packageName.toString(); 206 } 207 208 public static boolean isAsync(Method method) { 209 return method.getName().endsWith("Async") 210 && (method.getReturnType().equals(Response.class) || method.getReturnType().equals(Future .class)); 211 } 212 213 public static boolean isAsyncPolling(Method method) { 214 return method.getName().endsWith("Async") 215 && (method.getReturnType().equals(Response.class)); 216 } 217 218 public static boolean isAsyncCallback(Method method) { 219 Class [] paramTypes = method.getParameterTypes(); 220 return method.getName().endsWith("Async") 221 && (method.getReturnType().equals(Future .class) 222 && AsyncHandler.class.isAssignableFrom(paramTypes[paramTypes.length - 1])); 223 } 224 225 private static String normalizePackageNamePart(String name) { 226 StringBuffer sname = new StringBuffer (name.toLowerCase()); 227 228 for (int i = 0; i < sname.length(); i++) { 229 sname.setCharAt(i, Character.toLowerCase(sname.charAt(i))); 230 } 231 232 for (int i = 0; i < sname.length(); i++) { 233 if (!Character.isJavaIdentifierPart(sname.charAt(i))) { 234 sname.setCharAt(i, '_'); 235 } 236 } 237 238 if (isJavaKeyword(sname.toString())) { 239 sname.insert(0, '_'); 240 } 241 242 if (!Character.isJavaIdentifierStart(sname.charAt(0))) { 243 sname.insert(0, '_'); 244 } 245 246 return sname.toString(); 247 } 248 249 250 257 public static String nameToIdentifier(String name, IdentifierType type) { 258 259 if (null == name || name.length() == 0) { 260 return name; 261 } 262 263 266 boolean legalIdentifier = false; 267 StringBuffer buf = new StringBuffer (name); 268 legalIdentifier = Character.isJavaIdentifierStart(buf.charAt(0)); 269 270 for (int i = 1; i < name.length() && legalIdentifier; i++) { 271 legalIdentifier = legalIdentifier && Character.isJavaIdentifierPart(buf.charAt(i)); 272 } 273 274 boolean conventionalIdentifier = isConventionalIdentifier(buf, type); 275 if (legalIdentifier && conventionalIdentifier) { 276 if (JAXBUtils.isJavaKeyword(name) && type == IdentifierType.VARIABLE) { 277 name = normalizePackageNamePart(name.toString()); 278 } 279 return name; 280 } 281 282 284 List <String > words = new ArrayList <String >(); 285 286 StringTokenizer st = new StringTokenizer (name, XML_NAME_PUNCTUATION_STRING); 287 while (st.hasMoreTokens()) { 288 words.add(st.nextToken()); 289 } 290 291 for (int i = 0; i < words.size(); i++) { 292 splitWord(words, i); 293 } 294 295 return makeConventionalIdentifier(words, type); 296 } 297 298 private static void splitWord(List <String > words, int listIndex) { 299 String word = words.get(listIndex); 300 if (word.length() <= 1) { 301 return; 302 } 303 int index = listIndex + 1; 304 StringBuffer sword = new StringBuffer (word); 305 int first = 0; 306 char firstChar = sword.charAt(first); 307 if (Character.isLowerCase(firstChar)) { 308 sword.setCharAt(first, Character.toUpperCase(firstChar)); 309 } 310 int i = 1; 311 312 while (i < sword.length()) { 313 if (Character.isDigit(firstChar)) { 314 while (i < sword.length() && Character.isDigit(sword.charAt(i))) { 315 i++; 316 } 317 } else if (isCasedLetter(firstChar)) { 318 boolean previousIsLower = Character.isLowerCase(firstChar); 319 while (i < sword.length() && isCasedLetter(sword.charAt(i))) { 320 if (Character.isUpperCase(sword.charAt(i)) && previousIsLower) { 321 break; 322 } 323 previousIsLower = Character.isLowerCase(sword.charAt(i)); 324 i++; 325 } 326 } else { 327 while (i < sword.length() && (isMark(sword.charAt(i)) || !isCasedLetter(sword.charAt(i)))) { 329 i++; 330 } 331 } 332 333 338 339 String newWord = sword.substring(first, i); 340 words.add(index, newWord); 341 index++; 342 if (i >= sword.length()) { 343 break; 344 } else { 345 first = i; 346 firstChar = sword.charAt(first); 347 } 348 } 349 350 if (index > (listIndex + 1)) { 351 words.remove(listIndex); 352 } 353 } 354 355 private static boolean isMark(char c) { 356 return Character.isJavaIdentifierPart(c) && !Character.isLetter(c) && !Character.isDigit(c); 357 } 358 359 private static boolean isCasedLetter(char c) { 360 return Character.isUpperCase(c) || Character.isLowerCase(c); 361 } 362 363 private static boolean isConventionalIdentifier(StringBuffer buf, IdentifierType type) { 364 if (null == buf || buf.length() == 0) { 365 return false; 366 } 367 boolean result = false; 368 if (IdentifierType.CONSTANT == type) { 369 for (int i = 0; i < buf.length(); i++) { 370 if (Character.isLowerCase(buf.charAt(i))) { 371 return false; 372 } 373 } 374 result = true; 375 } else if (IdentifierType.VARIABLE == type) { 376 result = Character.isLowerCase(buf.charAt(0)); 377 } else { 378 int pos = 3; 379 if (IdentifierType.GETTER == type 380 && !(buf.length() >= pos 381 && "get".equals(buf.subSequence(0, 3)))) { 382 return false; 383 } else if (IdentifierType.SETTER == type 384 && !(buf.length() >= pos && "set".equals(buf.subSequence(0, 3)))) { 385 return false; 386 } else { 387 pos = 0; 388 } 389 result = Character.isUpperCase(buf.charAt(pos)); 390 } 391 return result; 392 } 393 394 private static String makeConventionalIdentifier(List <String > words, IdentifierType type) { 395 StringBuffer buf = new StringBuffer (); 396 boolean firstWord = true; 397 if (IdentifierType.GETTER == type) { 398 buf.append("get"); 399 } else if (IdentifierType.SETTER == type) { 400 buf.append("set"); 401 } 402 for (String w : words) { 403 int l = buf.length(); 404 if (l > 0 && IdentifierType.CONSTANT == type) { 405 buf.append('_'); 406 l++; 407 } 408 buf.append(w); 409 if (IdentifierType.CONSTANT == type) { 410 for (int i = l; i < buf.length(); i++) { 411 if (Character.isLowerCase(buf.charAt(i))) { 412 buf.setCharAt(i, Character.toUpperCase(buf.charAt(i))); 413 } 414 } 415 } else if (IdentifierType.VARIABLE == type) { 416 if (firstWord && Character.isUpperCase(buf.charAt(l))) { 417 buf.setCharAt(l, Character.toLowerCase(buf.charAt(l))); 418 } 419 } else { 420 if (firstWord && Character.isLowerCase(buf.charAt(l))) { 421 buf.setCharAt(l, Character.toUpperCase(buf.charAt(l))); 422 } 423 } 424 firstWord = false; 425 } 426 return buf.toString(); 427 } 428 429 } 430 | Popular Tags |