KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jaxb > JAXBUtil


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Emil Ong
27  */

28
29 package com.caucho.jaxb;
30
31 import javax.xml.bind.annotation.XmlType;
32 import javax.xml.namespace.QName JavaDoc;
33 import static java.lang.Character JavaDoc.*;
34 import java.lang.reflect.Method JavaDoc;
35 import java.lang.reflect.ParameterizedType JavaDoc;
36 import java.lang.reflect.Type JavaDoc;
37 import java.math.BigDecimal JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Calendar JavaDoc;
40 import java.util.Collection JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Map JavaDoc;
44
45 /**
46  * JAXB utilities.
47  */

48 public class JAXBUtil {
49   private static final Map JavaDoc<Class JavaDoc,String JavaDoc> _datatypeMap
50     = new HashMap JavaDoc<Class JavaDoc,String JavaDoc>();
51
52   public static void introspectClass(Class JavaDoc cl,
53                                      Collection JavaDoc<Class JavaDoc> jaxbClasses)
54   {
55     Method JavaDoc[] methods = cl.getMethods();
56
57     for (Method JavaDoc method : methods)
58       introspectMethod(method, jaxbClasses);
59   }
60
61   /**
62    * Finds all the classes mentioned in a method signature (return type and
63    * parameters) and adds them to the passed in classList. Pass in a set if
64    * you expect multiple references.
65    */

66   public static void introspectMethod(Method JavaDoc method,
67                                       Collection JavaDoc<Class JavaDoc> jaxbClasses)
68   {
69     introspectType(method.getReturnType(), jaxbClasses);
70
71     Type[] params = method.getGenericParameterTypes();
72
73     for (Type param : params)
74       introspectType(param, jaxbClasses);
75
76     /* XXX: create wrappers
77     Type[] exceptions = method.getGenericExceptionTypes();
78
79     for (Type exception : exceptions)
80       introspectType(exception, jaxbClasses);*/

81   }
82
83   /**
84    * Add all classes referenced by type to jaxbClasses.
85    */

86   private static void introspectType(Type type, Collection JavaDoc<Class JavaDoc> jaxbClasses)
87   {
88     if (type instanceof Class JavaDoc) {
89       Class JavaDoc cl = (Class JavaDoc) type;
90
91       if (! cl.isInterface())
92         jaxbClasses.add((Class JavaDoc) type);
93     }
94     else if (type instanceof ParameterizedType JavaDoc) {
95       ParameterizedType JavaDoc pType = (ParameterizedType JavaDoc) type;
96
97       introspectType(pType.getRawType(), jaxbClasses);
98       introspectType(pType.getOwnerType(), jaxbClasses);
99
100       Type[] arguments = pType.getActualTypeArguments();
101
102       for (Type argument : arguments)
103         introspectType(argument, jaxbClasses);
104     }
105     else if (type != null) {
106       // Type variables must be instantiated
107
throw new UnsupportedOperationException JavaDoc("Method arguments cannot have " +
108                                               "uninstantiated type variables " +
109                                               "or wildcards (" + type + ")");
110     }
111   }
112
113   public static String JavaDoc classBasename(Class JavaDoc cl)
114   {
115     int i = cl.getName().lastIndexOf('$');
116
117     if (i < 0)
118       i = cl.getName().lastIndexOf('.');
119
120     return cl.getName().substring(i + 1);
121   }
122
123   /**
124    * Tests for punctuation according to JAXB page 334.
125    */

126   private static boolean isPunctuation(char ch)
127   {
128     return "-.:\u00B7\u0387\u06DD\u06dd\u06de_".indexOf((int) ch) >= 0;
129   }
130
131   /**
132    * Tests for "uncased" characters.
133    */

134   private static boolean isUncased(char ch)
135   {
136     return (! isLowerCase(ch)) && (! isUpperCase(ch));
137   }
138
139   /**
140    * Splits a string into XML "words" as defined by the JAXB standard.
141    * (see page 162 and appendix D)
142    *
143    */

144   private static List JavaDoc<StringBuilder JavaDoc> splitIdentifier(String JavaDoc identifier)
145   {
146     List JavaDoc<StringBuilder JavaDoc> words = new ArrayList JavaDoc<StringBuilder JavaDoc>();
147     StringBuilder JavaDoc word = new StringBuilder JavaDoc();
148     char lastCh = 0;
149
150     for (int i = 0; i < identifier.length(); i++) {
151       char ch = identifier.charAt(i);
152
153       // punctuation shouldn't be common for the java -> xml direction
154
if (word.length() > 0 && isPunctuation(ch)) {
155         words.add(word);
156         word = new StringBuilder JavaDoc();
157       }
158       else if (isDigit(ch)) {
159         if (word.length() > 0 && ! isDigit(lastCh)) {
160           words.add(word);
161           word = new StringBuilder JavaDoc();
162         }
163
164         word.append(ch);
165       }
166       else if (i > 0) { // all of the following need lastCh
167
if (isLowerCase(lastCh) && isUpperCase(ch)) {
168           words.add(word);
169           word = new StringBuilder JavaDoc();
170           word.append(ch);
171         }
172         else if (isUpperCase(lastCh) && isLowerCase(ch)) {
173           // need to steal the last character from the current word
174
// for the next word (e.g. FOOBar -> { "FOO", "Bar" })
175

176           if (word.length() > 1) {
177             word.deleteCharAt(word.length() - 1);
178             words.add(word);
179           }
180
181           word = new StringBuilder JavaDoc();
182           word.append(lastCh);
183           word.append(ch);
184         }
185         else if (isLetter(lastCh) != isLetter(ch)) {
186           words.add(word);
187           word = new StringBuilder JavaDoc();
188           word.append(ch);
189         }
190         else if (isUncased(lastCh) != isUncased(ch)) {
191           words.add(word);
192           word = new StringBuilder JavaDoc();
193           word.append(ch);
194         }
195         else
196           word.append(ch);
197       }
198       else
199         word.append(ch);
200
201       lastCh = ch;
202     }
203
204     if (word.length() > 0)
205       words.add(word);
206
207     return words;
208   }
209
210   public static String JavaDoc identifierToXmlName(Class JavaDoc cl)
211   {
212     List JavaDoc<StringBuilder JavaDoc> words = splitIdentifier(classBasename(cl));
213     StringBuilder JavaDoc xmlName = new StringBuilder JavaDoc();
214
215     xmlName.append(toLowerCase(words.get(0).charAt(0)));
216     xmlName.append(words.get(0).substring(1));
217
218     for (int i = 1; i < words.size(); i++) {
219       if (words.get(i).length() > 0) {
220         xmlName.append(toUpperCase(words.get(i).charAt(0)));
221         xmlName.append(words.get(i).substring(1));
222       }
223     }
224
225     return xmlName.toString();
226   }
227
228   public static String JavaDoc getXmlSchemaDatatype(Class JavaDoc cl)
229   {
230     // XXX namespaces
231

232     if (_datatypeMap.containsKey(cl))
233       return _datatypeMap.get(cl);
234
235     String JavaDoc name = null;
236
237     if (cl.isAnnotationPresent(XmlType.class)) {
238       XmlType xmlType = (XmlType) cl.getAnnotation(XmlType.class);
239
240       if (! "##default".equals(xmlType.name()))
241         name = xmlType.name();
242     }
243
244     if (name == null)
245       name = identifierToXmlName(cl);
246
247     _datatypeMap.put(cl, name);
248
249     return name;
250   }
251
252   public static String JavaDoc qNameToString(QName JavaDoc qName)
253   {
254     if (qName.getPrefix() == null || "".equals(qName.getPrefix()))
255       return qName.getLocalPart();
256     else
257       return qName.getPrefix() + ':' + qName.getLocalPart();
258   }
259
260
261   static {
262     _datatypeMap.put(String JavaDoc.class, "xsd:string");
263
264     _datatypeMap.put(BigDecimal JavaDoc.class, "xsd:decimal");
265
266     _datatypeMap.put(Boolean JavaDoc.class, "xsd:boolean");
267     _datatypeMap.put(boolean.class, "xsd:boolean");
268
269     _datatypeMap.put(Byte JavaDoc[].class, "xsd:base64Binary"); // XXX hexBinary
270
_datatypeMap.put(byte[].class, "xsd:base64Binary"); // XXX hexBinary
271

272     _datatypeMap.put(Byte JavaDoc.class, "xsd:byte");
273     _datatypeMap.put(byte.class, "xsd:byte");
274
275     _datatypeMap.put(Character JavaDoc.class, "xsd:unsignedShort");
276     _datatypeMap.put(char.class, "xsd:unsignedShort");
277
278     _datatypeMap.put(Calendar JavaDoc.class, "xsd:date");
279
280     _datatypeMap.put(Double JavaDoc.class, "xsd:double");
281     _datatypeMap.put(double.class, "xsd:double");
282
283     _datatypeMap.put(Float JavaDoc.class, "xsd:float");
284     _datatypeMap.put(float.class, "xsd:float");
285
286     _datatypeMap.put(Integer JavaDoc.class, "xsd:int");
287     _datatypeMap.put(int.class, "xsd:int");
288
289     _datatypeMap.put(Long JavaDoc.class, "xsd:long");
290     _datatypeMap.put(long.class, "xsd:long");
291
292     _datatypeMap.put(Short JavaDoc.class, "xsd:short");
293     _datatypeMap.put(short.class, "xsd:short");
294   }
295 }
296
Popular Tags