KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > zeus > util > NamingUtils


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  */

19 package org.enhydra.zeus.util;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23
24 // Zeus imports
25
import org.enhydra.zeus.ZeusDefaults;
26
27 /**
28  * <p>
29  * <code>NamingUtils</code> is a Zeus utility class that provides methods
30  * which deal with the naming issues involved in data binding. Specifically,
31  * this class will deal with deriving Java class names, deriving Java
32  * variable names, deriving XML element names, and validating legal Java
33  * identifiers.
34  * <p>
35  *
36  * @author Brett McLaughlin
37  * @author Robert Sese
38  * @author Maciej Zawadzki
39  */

40 public class NamingUtils {
41
42     /** Prefix to append to names that clash with Java reserved words. */
43     public static final String JavaDoc XML_PREFIX = "xml";
44
45     /** The default alternative representation for illegal characters. */
46     public static final String JavaDoc DEFAULT_MAPPING = "";
47
48     /**
49      * A map of illegal characters mapped to legal alternative representations.
50      */

51     private static Map JavaDoc illegalCharMap = new HashMap JavaDoc();
52
53     /** A map of all the Java reserved words. */
54     private static HashMap JavaDoc reservedWords = new HashMap JavaDoc();
55
56     /** An array of all the Java reserved words to be stored in a map. */
57     private static String JavaDoc reservedWordsArray[] = { "abstract",
58         "boolean", "break", "byte", "case", "catch", "char", "class",
59         "char", "const", "continue", "default", "do", "double", "else",
60         "extends", "false", "final", "finally", "float", "for",
61         "goto", "if", "implements", "import", "instanceof", "int",
62         "interface", "long", "native", "new", "null", "package",
63         "private", "protected", "public", "return", "short", "static",
64         "super", "switch", "synchronized", "this", "throw", "throws",
65         "transient", "true", "try", "void", "volatile", "while" };
66
67     // Initialize the reserved words map and the illegal characters map.
68
static {
69         for (int i = 0; i < reservedWordsArray.length; i++) {
70             reservedWords.put(reservedWordsArray[i], new Integer JavaDoc(i));
71         }
72         reservedWordsArray = null;
73
74         // XXX: Add more illegal chars mappings...we don't have to check too
75
// many because we can assume XML naming rules, though
76
illegalCharMap.put(new Character JavaDoc('.'), DEFAULT_MAPPING);
77         illegalCharMap.put(new Character JavaDoc('-'), DEFAULT_MAPPING);
78         illegalCharMap.put(new Character JavaDoc(':'), DEFAULT_MAPPING);
79     }
80
81     /**
82      * <p>
83      * Prevent direct instantiation.
84      * </p>
85      */

86     private NamingUtils() {}
87     
88     /**
89      * <p>
90      * This will indicate whether the supplied name is a legal Java class
91      * name.
92      * </p>
93      *
94      * @param className the Java class name to check
95      * @return <code>boolean</code> - whether the supplied class is a legal
96      * Java class name.
97      */

98     public static boolean isLegalJavaClassName(String JavaDoc className) {
99         if (className == null) {
100             throw new IllegalArgumentException JavaDoc("A non-null String must be " +
101                 "supplied to NamingUtils methods.");
102         }
103         
104         for (int i=0, len=className.length(); i<len; i++) {
105             if ((i == 0) &&
106                 (!Character.isJavaIdentifierStart(className.charAt(i)))) {
107                 return false;
108             } else if (!Character.isJavaIdentifierPart(className.charAt(i))) {
109                 return false;
110             }
111         }
112         
113         // If we got here, all is OK
114
return true;
115     }
116     
117     /**
118      * <p>
119      * This will indicate whether the supplied name is a legal Java package
120      * name.
121      * </p>
122      *
123      * @param packageName the Java class name to check
124      * @return <code>boolean</code> - whether the supplied package is a legal
125      * Java package name.
126      */

127     public static boolean isLegalJavaPackageName(String JavaDoc packageName) {
128         if (packageName == null) {
129             throw new IllegalArgumentException JavaDoc("A non-null String must be " +
130                 "supplied to NamingUtils methods.");
131         }
132         
133         for (int i=0, len=packageName.length(); i<len; i++) {
134             if ((i == 0) &&
135                 (!Character.isJavaIdentifierStart(packageName.charAt(i)))) {
136                 return false;
137             } else if (
138                 (!Character.isJavaIdentifierPart(packageName.charAt(i))) &&
139                 (!(packageName.charAt(i) == '.'))) {
140
141                 return false;
142             }
143         }
144         
145         // If we got here, all is OK
146
return true;
147     }
148
149     /**
150      * <p>
151      * Returns the value that the given key is mapped to. This value will
152      * replace any occurence of the key when a name contains illegal
153      * characters for a Java identifier.
154      * </p>
155      *
156      * @param key the key mapped to the value to return.
157      * @return <code>String</code> - the value the given key is mapped to.
158      */

159     public static String JavaDoc getCharMapping(Character JavaDoc key) {
160         if (key == null) {
161             throw new IllegalArgumentException JavaDoc("A non-null Character must be " +
162                 "supplied to NamingUtils methods.");
163         }
164         
165         return (String JavaDoc)illegalCharMap.get(key);
166     }
167
168     /**
169      * <p>
170      * Maps the given key to the given value. This value will replace any
171      * occurence of the key when a name contains illegal characters
172      * for a Java identifier.
173      * </p>
174      *
175      * @param key the key to map the given value to.
176      * @param value the value to map the given key to.
177      */

178     public static void setCharMapping(Character JavaDoc key, String JavaDoc value) {
179         if (key == null) {
180             throw new IllegalArgumentException JavaDoc("A non-null char key must be " +
181                 "supplied to NamingUtils methods.");
182         }
183         if (value == null) {
184             throw new IllegalArgumentException JavaDoc("A non-null value must be " +
185                 "supplied to NamingUtils methods.");
186         }
187         
188         illegalCharMap.put(key, value);
189     }
190     
191     /**
192      * <p>
193      * Returns a conventional Java name from an XML name. Any illegal
194      * characters are replaced. Collision with reserved words is <i>not</i>
195      * checked, as this is not used directly in class generation.
196      * </p><p>
197      * For example, calling <code>getJavaName("my-element")</code> would
198      * return "myElement" as the Java class name.
199      * </p>
200      *
201      * @param xmlName the XML name to convert to a Java name.
202      * @return <code>String</code> - the converted Java name.
203      */

204     public static String JavaDoc getJavaName(String JavaDoc xmlName) {
205         if (xmlName == null) {
206             throw new IllegalArgumentException JavaDoc("A non-null XML name must be " +
207                 "supplied to NamingUtils methods.");
208         }
209         
210         // Handle the PCDATA special case
211
if (xmlName.equals(ZeusDefaults.PCDATA_XML_NAME)) {
212             return convertIllegalChars(ZeusDefaults.PCDATA_JAVA_NAME);
213         }
214         
215         return convertReservedWord(convertIllegalChars(xmlName));
216     }
217
218     /**
219      * <p>
220      * Returns the conventional Java variable name from an XML name. The
221      * initial character is uncapitalized, and any illegal characters are
222      * replaced. If there is a collision with a Java reserved word, the name
223      * is prefixed with <code>{@link #XML_PREFIX}</code>.
224      * </p><p>
225      * For example, calling <code>getJavaVariableName("XmlName")</code>
226      * would return "xmlName" as the Java variable name.
227      * </p>
228      *
229      * @param xmlName the XML name to convert to a variable name.
230      * @return <code>String</code> - the converted Java variable name.
231      */

232     public static String JavaDoc getJavaVariableName(String JavaDoc xmlName) {
233         if (xmlName == null) {
234             throw new IllegalArgumentException JavaDoc("A non-null XML name must " +
235                 "be supplied to NamingUtils methods.");
236         }
237         
238         // Handle the PCDATA special case
239
if (xmlName.equals(ZeusDefaults.PCDATA_XML_NAME)) {
240             return convertReservedWord(
241                 CapitalizationUtils.initialLower(
242                     ZeusDefaults.PCDATA_JAVA_NAME));
243         }
244         
245         return convertReservedWord(
246             convertIllegalChars(CapitalizationUtils.initialLower(xmlName)));
247     }
248
249     /**
250      * <p>
251      * Returns the Java variable name from a Java class name assuming that the
252      * variable will be a collection based variable (i.e. ending with "List"
253      * as in "myVariableList"). The initial character is uncapitalized, and
254      * any illegal characters are replaced. There is no check for a
255      * collision with a Java reserved word because the assumption is that
256      * the variable has some word appended to it that identifies the fact
257      * that the variable denotes a collection.
258      * </p><p>
259      * For example, calling
260      * <code>getJavaCollectionVariableName("MyClass")</code> would return
261      * "myClass" as the Java variable name.
262      * </p>
263      *
264      * @param className the class name to convert to a collection based
265      * variable name.
266      * @return <code>String</code> - the converted Java variable name.
267      */

268     public static String JavaDoc getJavaCollectionVariableName(String JavaDoc className) {
269         if (className == null) {
270             throw new IllegalArgumentException JavaDoc("A non-null class name must " +
271                 "be supplied to NamingUtils methods.");
272         }
273         
274         return convertReservedWord(
275             convertIllegalChars(CapitalizationUtils.initialLower(className)));
276     }
277     
278     /**
279      * <p>
280      * Returns the conventional Java class name from an XML name. The initial
281      * character is capitalized, and any illegal characters are replaced.
282      * There is no check for a collision with a Java reserved word because
283      * all Java reserved words have their initial character lower case.
284      * </p><p>
285      * For example, calling <code>getJavaClassName("my-element")</code> would
286      * return "MyElement" as the Java class name.
287      * </p>
288      *
289      * @param xmlName the XML name to convert to a Java class name.
290      * @return <code>String</code> - the converted Java name.
291      */

292     public static String JavaDoc getJavaClassName(String JavaDoc xmlName) {
293         if (xmlName == null) {
294             throw new IllegalArgumentException JavaDoc("A non-null XML name must be " +
295                 "supplied to NamingUtils methods.");
296         }
297         
298         return convertReservedWord(
299             convertIllegalChars(CapitalizationUtils.initialUpper(xmlName)));
300     }
301     
302     /**
303      * <p>
304      * This will handle conversion from an XML type to a Java type. It first
305      * attempts to perform an XML Schema type to Java type conversion. For
306      * example, if the XML type is "string", it would convert this to
307      * the Java type "String". If that is unsuccessful, it returns the
308      * type unchanged, assuming that it is a proper Java class name.
309      * </p>
310      *
311      * @param xmlType the XML type to convert to a Java type.
312      * @return <code>String</code> - the converted Java type.
313      */

314     public static String JavaDoc getJavaType(String JavaDoc xmlType) {
315         String JavaDoc javaType;
316         try {
317             javaType = SchemaUtils.getJavaType(xmlType);
318             return javaType;
319         } catch (UnsupportedSchemaTypeException e) {
320             // ignored
321
}
322         
323         // Ensure a legal Java class name is returned
324
return getJavaClassName(xmlType);
325     }
326     
327     /**
328      * <p>
329      * Returns the XML name from a typical accessor method. The naming
330      * convention for such a method is "get&lt;variable-name&gt;". The first
331      * three characters are discarded, and the initial character is
332      * uncapitalized.
333      * </p><p>
334      * For example, calling
335      * <code>getXMLElementNameFromAccessor("getMyVariable")</code> would
336      * return "myVariable" as the XML name. This method would also work
337      * with typical mutator methods.
338      * </p>
339      *
340      * @param accessor the name of the accessor method to derive the XML name
341      * from.
342      * @return <code>String</code> - the converted XML name.
343      */

344     public static String JavaDoc getXMLElementNameFromAccessor(String JavaDoc accessor) {
345         if (accessor == null) {
346             throw new IllegalArgumentException JavaDoc("A non-null accessor must " +
347                 "be supplied to NamingUtils methods.");
348         }
349         
350         return CapitalizationUtils.initialLower(accessor.substring(3));
351     }
352     
353     /**
354      * <p>
355      * This will take a fully qualified Java class, and return just the name
356      * of the class, without any package qualifier. For example, invoking
357      * <code>removePackage("java.util.List");</code> would return
358      * "List".
359      * </p>
360      *
361      * @param className the Java class name to remove the package from.
362      * @return <code>String</code> - the Java class, without package.
363      */

364     public static String JavaDoc removePackage(String JavaDoc className) {
365         String JavaDoc returnValue = className;
366         
367         if (returnValue.indexOf(".") > -1) {
368             returnValue = returnValue.substring(
369                 returnValue.lastIndexOf(".") + 1);
370         }
371         
372         return returnValue;
373     }
374
375     /**
376      * <p>
377      * Checks whether the given name collides with a Java reserved word. If
378      * there is a collision, the name is returned prefixed with
379      * <code>{@link #XML_PREFIX}</code>, else it is returned unchanged.
380      * </p>
381      *
382      * @param name the name to check.
383      * @return <code>String</code> - the converted name if there is a collision
384      * with a Java reserved word, else the same name.
385      */

386     private static String JavaDoc convertReservedWord(String JavaDoc name) {
387         if (name == null) {
388             throw new IllegalArgumentException JavaDoc("A non-null name must " +
389                 "be supplied to NamingUtils methods.");
390         }
391         
392         if (reservedWords.get(name) == null) {
393             return name;
394         } else {
395             return new StringBuffer JavaDoc().append(XML_PREFIX)
396                 .append(name).toString();
397         }
398     }
399
400     /**
401      * <p>
402      * Checks whether each character in the given name is valid for a Java
403      * identifier. If there are illegal characters, the name is returned
404      * with each illegal character replaced with its value in the internal
405      * map of illegal <code>Character</code>s to replacement
406      * <code>String</code>s, else the same name is returned. If the
407      * illegal character can be interpreted as a separator character
408      * (such as the '-' in my-attribute), then the character following the
409      * separator character will be capitalized (i.e. my-attribute becomes
410      * myAttribute).
411      * </p>
412      *
413      * @param name the name to check.
414      * @return <code>String</code> - the converted name if illegal characters
415      * are present, else the same name.
416      */

417     private static String JavaDoc convertIllegalChars(String JavaDoc name) {
418         if (name == null) {
419             throw new IllegalArgumentException JavaDoc("A non-null name must " +
420                 "be supplied to NamingUtils methods.");
421         }
422         
423         StringBuffer JavaDoc verifiedName = new StringBuffer JavaDoc();
424         char[] characters = name.toCharArray();
425
426         // XXX: Uppercase the next letter after all illegal chars, or just the
427
// ones that can be interpreted as separator chars?
428
boolean upperNext = false;
429
430         for (int i = 0; i < characters.length; i++) {
431             char c = characters[i];
432
433             if (i == 0) {
434                 if (Character.isJavaIdentifierStart(c) == false) {
435                     String JavaDoc legalValue =
436                         (String JavaDoc) illegalCharMap.get(new Character JavaDoc(c));
437
438                     if (legalValue == null) {
439
440                         // XXX: Throw an exception or append DEFAULT_MAPPING?
441
throw new IllegalArgumentException JavaDoc("No mapping for " +
442                             "illegal character: " + c);
443                     } else {
444                         verifiedName.append(legalValue);
445
446                         // XXX Does it make sense to uppercase the next char
447
// if the illegal char is the first char of the
448
// identifier?
449
upperNext = true;
450                     }
451                 } else {
452                     verifiedName.append(c);
453                 }
454             } else {
455                 if (Character.isJavaIdentifierPart(c) == false) {
456                     String JavaDoc legalValue =
457                         (String JavaDoc) illegalCharMap.get(new Character JavaDoc(c));
458
459                     if (legalValue == null) {
460
461                         // XXX: Throw an exception or append DEFAULT_MAPPING?
462
throw new IllegalArgumentException JavaDoc("No mapping for " +
463                             "illegal character: " + c);
464                     } else {
465                         verifiedName.append(legalValue);
466                         upperNext = true;
467                     }
468                 } else {
469                     if (upperNext) {
470                         verifiedName.append(Character.toUpperCase(c));
471                         upperNext = false;
472                     } else {
473                         verifiedName.append(c);
474                     }
475                 }
476             }
477         }
478         return verifiedName.toString();
479     }
480 }
481
Popular Tags