KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > jaxb > JAXBUtils


1 package org.objectweb.celtix.jaxb;
2
3 import java.lang.reflect.Method JavaDoc;
4 import java.net.URI JavaDoc;
5 import java.net.URISyntaxException JavaDoc;
6
7 import java.util.ArrayList JavaDoc;
8 import java.util.Arrays JavaDoc;
9 import java.util.HashMap JavaDoc;
10 import java.util.HashSet JavaDoc;
11 import java.util.List JavaDoc;
12 import java.util.Map JavaDoc;
13 import java.util.Set JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15 import java.util.concurrent.Future JavaDoc;
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 JavaDoc JAXB_URI = "http://java.sun.com/xml/ns/jaxb";
32     
33     private static final Set JavaDoc<String JavaDoc> KEYWORDS = new HashSet JavaDoc<String JavaDoc>(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         /* hyphen */ '\u002D',
48         /* period */ '\u002E',
49         /* colon */'\u003A',
50         /* dot */ '\u00B7',
51         /* greek ano teleia */ '\u0387',
52         /* arabic end of ayah */ '\u06DD',
53         /* arabic start of rub el hizb */'\u06DE',
54         /* underscore */ '\u005F',
55     };
56     
57     private static final String JavaDoc XML_NAME_PUNCTUATION_STRING = new String JavaDoc(XML_NAME_PUNCTUATION_CHARS);
58     
59     private static final Map JavaDoc<String JavaDoc, String JavaDoc> BUILTIN_DATATYPES_MAP;
60     private static final Map JavaDoc<String JavaDoc, Class JavaDoc> HOLDER_TYPES_MAP;
61     
62     static {
63         BUILTIN_DATATYPES_MAP = new HashMap JavaDoc<String JavaDoc, String JavaDoc>();
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 JavaDoc<String JavaDoc, Class JavaDoc>();
93         HOLDER_TYPES_MAP.put("int", java.lang.Integer JavaDoc.class);
94         HOLDER_TYPES_MAP.put("long", java.lang.Long JavaDoc.class);
95         HOLDER_TYPES_MAP.put("short", java.lang.Short JavaDoc.class);
96         HOLDER_TYPES_MAP.put("float", java.lang.Float JavaDoc.class);
97         HOLDER_TYPES_MAP.put("double", java.lang.Double JavaDoc.class);
98         HOLDER_TYPES_MAP.put("boolean", java.lang.Boolean JavaDoc.class);
99         HOLDER_TYPES_MAP.put("byte", java.lang.Byte JavaDoc.class);
100     }
101     
102     
103     /**
104      * prevents instantiation
105      *
106      */

107     private JAXBUtils() {
108     }
109     
110     public static String JavaDoc builtInTypeToJavaType(String JavaDoc type) {
111         return BUILTIN_DATATYPES_MAP.get(type);
112     }
113     
114     public static Class JavaDoc holderClass(String JavaDoc type) {
115         return HOLDER_TYPES_MAP.get(type);
116     }
117     
118     /**
119      * Checks if the specified word is a Java keyword (as of 1.5).
120      *
121      * @param word the word to check.
122      * @return true if the word is a keyword.
123      */

124     public static boolean isJavaKeyword(String JavaDoc word) {
125         return KEYWORDS.contains(word);
126     }
127
128     /**
129      * Generates a Java package name from a URI according to the
130      * algorithm outlined in JAXB 2.0.
131      *
132      * @param namespaceURI the namespace URI.
133      * @return the package name.
134      */

135     public static String JavaDoc namespaceURIToPackage(String JavaDoc namespaceURI) {
136         try {
137             return nameSpaceURIToPackage(new URI JavaDoc(namespaceURI));
138         } catch (URISyntaxException JavaDoc ex) {
139             return null;
140         }
141     }
142     
143     /**
144      * Generates a Java package name from a URI according to the
145      * algorithm outlined in JAXB 2.0.
146      *
147      * @param namespaceURI the namespace URI.
148      * @return the package name.
149      */

150     public static String JavaDoc nameSpaceURIToPackage(URI JavaDoc uri) {
151         
152         StringBuffer JavaDoc packageName = new StringBuffer JavaDoc();
153         
154         String JavaDoc 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 JavaDoc st = new StringTokenizer JavaDoc(authority, ".");
170             if (st.hasMoreTokens()) {
171                 String JavaDoc 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 JavaDoc path = uri.getPath();
193         int index = path.lastIndexOf('.');
194         if (index < 0) {
195             index = path.length();
196         }
197         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(path.substring(0, index), "/");
198         while (st.hasMoreTokens()) {
199             String JavaDoc 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 JavaDoc method) {
209         return method.getName().endsWith("Async")
210             && (method.getReturnType().equals(Response.class) || method.getReturnType().equals(Future JavaDoc.class));
211     }
212     
213     public static boolean isAsyncPolling(Method JavaDoc method) {
214         return method.getName().endsWith("Async")
215             && (method.getReturnType().equals(Response.class));
216     }
217     
218     public static boolean isAsyncCallback(Method JavaDoc method) {
219         Class JavaDoc[] paramTypes = method.getParameterTypes();
220         return method.getName().endsWith("Async")
221             && (method.getReturnType().equals(Future JavaDoc.class)
222             && AsyncHandler.class.isAssignableFrom(paramTypes[paramTypes.length - 1]));
223     }
224     
225     private static String JavaDoc normalizePackageNamePart(String JavaDoc name) {
226         StringBuffer JavaDoc sname = new StringBuffer JavaDoc(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     /**
251      * Converts an XML name to a Java identifier according to the mapping
252      * algorithm outlines in the JAXB specification
253      *
254      * @param name the XML name
255      * @return the Java identifier
256      */

257     public static String JavaDoc nameToIdentifier(String JavaDoc name, IdentifierType type) {
258
259         if (null == name || name.length() == 0) {
260             return name;
261         }
262
263         // algorithm will not change an XML name that is already a legal and
264
// conventional (!) Java class, method, or constant identifier
265

266         boolean legalIdentifier = false;
267         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(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         // split into words
283

284         List JavaDoc<String JavaDoc> words = new ArrayList JavaDoc<String JavaDoc>();
285
286         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(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 JavaDoc<String JavaDoc> words, int listIndex) {
299         String JavaDoc word = words.get(listIndex);
300         if (word.length() <= 1) {
301             return;
302         }
303         int index = listIndex + 1;
304         StringBuffer JavaDoc sword = new StringBuffer JavaDoc(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                 // first must be a mark or an uncased letter
328
while (i < sword.length() && (isMark(sword.charAt(i)) || !isCasedLetter(sword.charAt(i)))) {
329                     i++;
330                 }
331             }
332             
333             // characters from first to i are all either
334
// * digits
335
// * upper or lower case letters, with only the first one an upper
336
// * uncased letters or marks
337

338             
339             String JavaDoc 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 JavaDoc 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 JavaDoc makeConventionalIdentifier(List JavaDoc<String JavaDoc> words, IdentifierType type) {
395         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
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 JavaDoc 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