1/*
2 * Copyright (c) 2003, 2013, 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
26package javax.xml.bind;
27
28import javax.xml.namespace.NamespaceContext;
29
30/**
31 * <p>
32 * The javaType binding declaration can be used to customize the binding of
33 * an XML schema datatype to a Java datatype. Customizations can involve
34 * writing a parse and print method for parsing and printing lexical
35 * representations of a XML schema datatype respectively. However, writing
36 * parse and print methods requires knowledge of the lexical representations (
37 * <a href="http://www.w3.org/TR/xmlschema-2/"> XML Schema Part2: Datatypes
38 * specification </a>) and hence may be difficult to write.
39 * </p>
40 * <p>
41 * This class makes it easier to write parse and print methods. It defines
42 * static parse and print methods that provide access to a JAXB provider's
43 * implementation of parse and print methods. These methods are invoked by
44 * custom parse and print methods. For example, the binding of xsd:dateTime
45 * to a long can be customized using parse and print methods as follows:
46 * <blockquote>
47 *    <pre>
48 *    // Customized parse method
49 *    public long myParseCal( String dateTimeString ) {
50 *        java.util.Calendar cal = DatatypeConverter.parseDateTime(dateTimeString);
51 *        long longval = convert_calendar_to_long(cal); //application specific
52 *        return longval;
53 *    }
54 *
55 *    // Customized print method
56 *    public String myPrintCal( Long longval ) {
57 *        java.util.Calendar cal = convert_long_to_calendar(longval) ; //application specific
58 *        String dateTimeString = DatatypeConverter.printDateTime(cal);
59 *        return dateTimeString;
60 *    }
61 *    </pre>
62 * </blockquote>
63 * <p>
64 * There is a static parse and print method corresponding to each parse and
65 * print method respectively in the {@link DatatypeConverterInterface
66 * DatatypeConverterInterface}.
67 * <p>
68 * The static methods defined in the class can also be used to specify
69 * a parse or a print method in a javaType binding declaration.
70 * </p>
71 * <p>
72 * JAXB Providers are required to call the
73 * {@link #setDatatypeConverter(DatatypeConverterInterface)
74 * setDatatypeConverter} api at some point before the first marshal or unmarshal
75 * operation (perhaps during the call to JAXBContext.newInstance).  This step is
76 * necessary to configure the converter that should be used to perform the
77 * print and parse functionality.
78 * </p>
79 *
80 * <p>
81 * A print method for a XML schema datatype can output any lexical
82 * representation that is valid with respect to the XML schema datatype.
83 * If an error is encountered during conversion, then an IllegalArgumentException,
84 * or a subclass of IllegalArgumentException must be thrown by the method.
85 * </p>
86 *
87 * @author <ul><li>Sekhar Vajjhala, Sun Microsystems, Inc.</li><li>Joe Fialli, Sun Microsystems Inc.</li><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li><li>Ryan Shoemaker,Sun Microsystems Inc.</li></ul>
88 * @see DatatypeConverterInterface
89 * @see ParseConversionEvent
90 * @see PrintConversionEvent
91 * @since 1.6, JAXB 1.0
92 */
93
94final public class DatatypeConverter {
95
96    // delegate to this instance of DatatypeConverter
97    private static volatile DatatypeConverterInterface theConverter = null;
98
99    private final static JAXBPermission SET_DATATYPE_CONVERTER_PERMISSION =
100                           new JAXBPermission("setDatatypeConverter");
101
102    private DatatypeConverter() {
103        // private constructor
104    }
105
106    /**
107     * This method is for JAXB provider use only.
108     * <p>
109     * JAXB Providers are required to call this method at some point before
110     * allowing any of the JAXB client marshal or unmarshal operations to
111     * occur.  This is necessary to configure the datatype converter that
112     * should be used to perform the print and parse conversions.
113     *
114     * <p>
115     * Calling this api repeatedly will have no effect - the
116     * DatatypeConverterInterface instance passed into the first invocation is
117     * the one that will be used from then on.
118     *
119     * @param converter an instance of a class that implements the
120     * DatatypeConverterInterface class - this parameter must not be null.
121     * @throws IllegalArgumentException if the parameter is null
122     * @throws SecurityException
123     *      If the {@link SecurityManager} in charge denies the access to
124     *      set the datatype converter.
125     * @see JAXBPermission
126     */
127    public static void setDatatypeConverter( DatatypeConverterInterface converter ) {
128        if( converter == null ) {
129            throw new IllegalArgumentException(
130                Messages.format( Messages.CONVERTER_MUST_NOT_BE_NULL ) );
131        } else if( theConverter == null ) {
132            SecurityManager sm = System.getSecurityManager();
133            if (sm != null)
134                sm.checkPermission(SET_DATATYPE_CONVERTER_PERMISSION);
135            theConverter = converter;
136        }
137    }
138
139    private static synchronized void initConverter() {
140        theConverter = new DatatypeConverterImpl();
141    }
142
143    /**
144     * <p>
145     * Convert the lexical XSD string argument into a String value.
146     * @param lexicalXSDString
147     *     A string containing a lexical representation of
148     *     xsd:string.
149     * @return
150     *     A String value represented by the string argument.
151     */
152    public static String parseString( String lexicalXSDString ) {
153        if (theConverter == null) initConverter();
154        return theConverter.parseString( lexicalXSDString );
155    }
156
157    /**
158     * <p>
159     * Convert the string argument into a BigInteger value.
160     * @param lexicalXSDInteger
161     *     A string containing a lexical representation of
162     *     xsd:integer.
163     * @return
164     *     A BigInteger value represented by the string argument.
165     * @throws NumberFormatException <code>lexicalXSDInteger</code> is not a valid string representation of a {@link java.math.BigInteger} value.
166     */
167    public static java.math.BigInteger parseInteger( String lexicalXSDInteger ) {
168        if (theConverter == null) initConverter();
169        return theConverter.parseInteger( lexicalXSDInteger );
170    }
171
172    /**
173     * <p>
174     * Convert the string argument into an int value.
175     * @param lexicalXSDInt
176     *     A string containing a lexical representation of
177     *     xsd:int.
178     * @return
179     *     A int value represented by the string argument.
180     * @throws NumberFormatException <code>lexicalXSDInt</code> is not a valid string representation of an <code>int</code> value.
181     */
182    public static int parseInt( String lexicalXSDInt ) {
183        if (theConverter == null) initConverter();
184        return theConverter.parseInt( lexicalXSDInt );
185    }
186
187    /**
188     * <p>
189     * Converts the string argument into a long value.
190     * @param lexicalXSDLong
191     *     A string containing lexical representation of
192     *     xsd:long.
193     * @return
194     *     A long value represented by the string argument.
195     * @throws NumberFormatException <code>lexicalXSDLong</code> is not a valid string representation of a <code>long</code> value.
196     */
197    public static long parseLong( String lexicalXSDLong ) {
198        if (theConverter == null) initConverter();
199        return theConverter.parseLong( lexicalXSDLong );
200    }
201
202    /**
203     * <p>
204     * Converts the string argument into a short value.
205     * @param lexicalXSDShort
206     *     A string containing lexical representation of
207     *     xsd:short.
208     * @return
209     *     A short value represented by the string argument.
210     * @throws NumberFormatException <code>lexicalXSDShort</code> is not a valid string representation of a <code>short</code> value.
211     */
212    public static short parseShort( String lexicalXSDShort ) {
213        if (theConverter == null) initConverter();
214        return theConverter.parseShort( lexicalXSDShort );
215    }
216
217    /**
218     * <p>
219     * Converts the string argument into a BigDecimal value.
220     * @param lexicalXSDDecimal
221     *     A string containing lexical representation of
222     *     xsd:decimal.
223     * @return
224     *     A BigDecimal value represented by the string argument.
225     * @throws NumberFormatException <code>lexicalXSDDecimal</code> is not a valid string representation of {@link java.math.BigDecimal}.
226     */
227    public static java.math.BigDecimal parseDecimal( String lexicalXSDDecimal ) {
228        if (theConverter == null) initConverter();
229        return theConverter.parseDecimal( lexicalXSDDecimal );
230    }
231
232    /**
233     * <p>
234     * Converts the string argument into a float value.
235     * @param lexicalXSDFloat
236     *     A string containing lexical representation of
237     *     xsd:float.
238     * @return
239     *     A float value represented by the string argument.
240     * @throws NumberFormatException <code>lexicalXSDFloat</code> is not a valid string representation of a <code>float</code> value.
241     */
242    public static float parseFloat( String lexicalXSDFloat ) {
243        if (theConverter == null) initConverter();
244        return theConverter.parseFloat( lexicalXSDFloat );
245    }
246
247    /**
248     * <p>
249     * Converts the string argument into a double value.
250     * @param lexicalXSDDouble
251     *     A string containing lexical representation of
252     *     xsd:double.
253     * @return
254     *     A double value represented by the string argument.
255     * @throws NumberFormatException <code>lexicalXSDDouble</code> is not a valid string representation of a <code>double</code> value.
256     */
257    public static double parseDouble( String lexicalXSDDouble ) {
258        if (theConverter == null) initConverter();
259        return theConverter.parseDouble( lexicalXSDDouble );
260    }
261
262    /**
263     * <p>
264     * Converts the string argument into a boolean value.
265     * @param lexicalXSDBoolean
266     *     A string containing lexical representation of
267     *     xsd:boolean.
268     * @return
269     *     A boolean value represented by the string argument.
270     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:boolean.
271     */
272    public static boolean parseBoolean( String lexicalXSDBoolean ) {
273        if (theConverter == null) initConverter();
274        return theConverter.parseBoolean( lexicalXSDBoolean );
275    }
276
277    /**
278     * <p>
279     * Converts the string argument into a byte value.
280     * @param lexicalXSDByte
281     *     A string containing lexical representation of
282     *     xsd:byte.
283     * @return
284     *     A byte value represented by the string argument.
285     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:byte.
286     */
287    public static byte parseByte( String lexicalXSDByte ) {
288        if (theConverter == null) initConverter();
289        return theConverter.parseByte( lexicalXSDByte );
290    }
291
292    /**
293     * <p>
294     * Converts the string argument into a byte value.
295     *
296     * <p>
297     * String parameter {@code lexicalXSDQname} must conform to lexical value space specifed at
298     * <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part 2:Datatypes specification:QNames</a>
299     *
300     * @param lexicalXSDQName
301     *     A string containing lexical representation of xsd:QName.
302     * @param nsc
303     *     A namespace context for interpreting a prefix within a QName.
304     * @return
305     *     A QName value represented by the string argument.
306     * @throws IllegalArgumentException  if string parameter does not conform to XML Schema Part 2 specification or
307     *      if namespace prefix of {@code lexicalXSDQname} is not bound to a URI in NamespaceContext {@code nsc}.
308     */
309    public static javax.xml.namespace.QName parseQName( String lexicalXSDQName,
310                                                    NamespaceContext nsc) {
311        if (theConverter == null) initConverter();
312        return theConverter.parseQName( lexicalXSDQName, nsc );
313    }
314
315    /**
316     * <p>
317     * Converts the string argument into a Calendar value.
318     * @param lexicalXSDDateTime
319     *     A string containing lexical representation of
320     *     xsd:datetime.
321     * @return
322     *     A Calendar object represented by the string argument.
323     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:dateTime.
324     */
325    public static java.util.Calendar parseDateTime( String lexicalXSDDateTime ) {
326        if (theConverter == null) initConverter();
327        return theConverter.parseDateTime( lexicalXSDDateTime );
328    }
329
330    /**
331     * <p>
332     * Converts the string argument into an array of bytes.
333     * @param lexicalXSDBase64Binary
334     *     A string containing lexical representation
335     *     of xsd:base64Binary.
336     * @return
337     *     An array of bytes represented by the string argument.
338     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:base64Binary
339     */
340    public static byte[] parseBase64Binary( String lexicalXSDBase64Binary ) {
341        if (theConverter == null) initConverter();
342        return theConverter.parseBase64Binary( lexicalXSDBase64Binary );
343    }
344
345    /**
346     * <p>
347     * Converts the string argument into an array of bytes.
348     * @param lexicalXSDHexBinary
349     *     A string containing lexical representation of
350     *     xsd:hexBinary.
351     * @return
352     *     An array of bytes represented by the string argument.
353     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:hexBinary.
354     */
355   public static byte[] parseHexBinary( String lexicalXSDHexBinary ) {
356        if (theConverter == null) initConverter();
357        return theConverter.parseHexBinary( lexicalXSDHexBinary );
358    }
359
360    /**
361     * <p>
362     * Converts the string argument into a long value.
363     * @param lexicalXSDUnsignedInt
364     *     A string containing lexical representation
365     *     of xsd:unsignedInt.
366     * @return
367     *     A long value represented by the string argument.
368     * @throws NumberFormatException if string parameter can not be parsed into a {@code long} value.
369     */
370    public static long parseUnsignedInt( String lexicalXSDUnsignedInt ) {
371        if (theConverter == null) initConverter();
372        return theConverter.parseUnsignedInt( lexicalXSDUnsignedInt );
373    }
374
375    /**
376     * <p>
377     * Converts the string argument into an int value.
378     * @param lexicalXSDUnsignedShort
379     *     A string containing lexical
380     *     representation of xsd:unsignedShort.
381     * @return
382     *     An int value represented by the string argument.
383     * @throws NumberFormatException if string parameter can not be parsed into an {@code int} value.
384     */
385    public static int   parseUnsignedShort( String lexicalXSDUnsignedShort ) {
386        if (theConverter == null) initConverter();
387        return theConverter.parseUnsignedShort( lexicalXSDUnsignedShort );
388    }
389
390    /**
391     * <p>
392     * Converts the string argument into a Calendar value.
393     * @param lexicalXSDTime
394     *     A string containing lexical representation of
395     *     xsd:time.
396     * @return
397     *     A Calendar value represented by the string argument.
398     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:Time.
399     */
400    public static java.util.Calendar parseTime( String lexicalXSDTime ) {
401        if (theConverter == null) initConverter();
402        return theConverter.parseTime( lexicalXSDTime );
403    }
404    /**
405     * <p>
406     * Converts the string argument into a Calendar value.
407     * @param lexicalXSDDate
408     *      A string containing lexical representation of
409     *     xsd:Date.
410     * @return
411     *     A Calendar value represented by the string argument.
412     * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:Date.
413     */
414    public static java.util.Calendar parseDate( String lexicalXSDDate ) {
415        if (theConverter == null) initConverter();
416        return theConverter.parseDate( lexicalXSDDate );
417    }
418
419    /**
420     * <p>
421     * Return a string containing the lexical representation of the
422     * simple type.
423     * @param lexicalXSDAnySimpleType
424     *     A string containing lexical
425     *     representation of the simple type.
426     * @return
427     *     A string containing the lexical representation of the
428     *     simple type.
429     */
430    public static String parseAnySimpleType( String lexicalXSDAnySimpleType ) {
431        if (theConverter == null) initConverter();
432        return theConverter.parseAnySimpleType( lexicalXSDAnySimpleType );
433    }
434    /**
435     * <p>
436     * Converts the string argument into a string.
437     * @param val
438     *     A string value.
439     * @return
440     *     A string containing a lexical representation of xsd:string.
441     */
442     // also indicate the print methods produce a lexical
443     // representation for given Java datatypes.
444
445    public static String printString( String val ) {
446        if (theConverter == null) initConverter();
447        return theConverter.printString( val );
448    }
449
450    /**
451     * <p>
452     * Converts a BigInteger value into a string.
453     * @param val
454     *     A BigInteger value
455     * @return
456     *     A string containing a lexical representation of xsd:integer
457     * @throws IllegalArgumentException {@code val} is null.
458     */
459    public static String printInteger( java.math.BigInteger val ) {
460        if (theConverter == null) initConverter();
461        return theConverter.printInteger( val );
462    }
463
464    /**
465     * <p>
466     * Converts an int value into a string.
467     * @param val
468     *     An int value
469     * @return
470     *     A string containing a lexical representation of xsd:int
471     */
472    public static String printInt( int val ) {
473        if (theConverter == null) initConverter();
474        return theConverter.printInt( val );
475    }
476
477    /**
478     * <p>
479     * Converts A long value into a string.
480     * @param val
481     *     A long value
482     * @return
483     *     A string containing a lexical representation of xsd:long
484     */
485    public static String printLong( long val ) {
486        if (theConverter == null) initConverter();
487        return theConverter.printLong( val );
488    }
489
490    /**
491     * <p>
492     * Converts a short value into a string.
493     * @param val
494     *     A short value
495     * @return
496     *     A string containing a lexical representation of xsd:short
497     */
498    public static String printShort( short val ) {
499        if (theConverter == null) initConverter();
500        return theConverter.printShort( val );
501    }
502
503    /**
504     * <p>
505     * Converts a BigDecimal value into a string.
506     * @param val
507     *     A BigDecimal value
508     * @return
509     *     A string containing a lexical representation of xsd:decimal
510     * @throws IllegalArgumentException {@code val} is null.
511     */
512    public static String printDecimal( java.math.BigDecimal val ) {
513        if (theConverter == null) initConverter();
514        return theConverter.printDecimal( val );
515    }
516
517    /**
518     * <p>
519     * Converts a float value into a string.
520     * @param val
521     *     A float value
522     * @return
523     *     A string containing a lexical representation of xsd:float
524     */
525    public static String printFloat( float val ) {
526        if (theConverter == null) initConverter();
527        return theConverter.printFloat( val );
528    }
529
530    /**
531     * <p>
532     * Converts a double value into a string.
533     * @param val
534     *     A double value
535     * @return
536     *     A string containing a lexical representation of xsd:double
537     */
538    public static String printDouble( double val ) {
539        if (theConverter == null) initConverter();
540        return theConverter.printDouble( val );
541    }
542
543    /**
544     * <p>
545     * Converts a boolean value into a string.
546     * @param val
547     *     A boolean value
548     * @return
549     *     A string containing a lexical representation of xsd:boolean
550     */
551    public static String printBoolean( boolean val ) {
552        if (theConverter == null) initConverter();
553        return theConverter.printBoolean( val );
554    }
555
556    /**
557     * <p>
558     * Converts a byte value into a string.
559     * @param val
560     *     A byte value
561     * @return
562     *     A string containing a lexical representation of xsd:byte
563     */
564    public static String printByte( byte val ) {
565        if (theConverter == null) initConverter();
566        return theConverter.printByte( val );
567    }
568
569    /**
570     * <p>
571     * Converts a QName instance into a string.
572     * @param val
573     *     A QName value
574     * @param nsc
575     *     A namespace context for interpreting a prefix within a QName.
576     * @return
577     *     A string containing a lexical representation of QName
578     * @throws IllegalArgumentException if {@code val} is null or
579     * if {@code nsc} is non-null or {@code nsc.getPrefix(nsprefixFromVal)} is null.
580     */
581    public static String printQName( javax.xml.namespace.QName val,
582                                     NamespaceContext nsc ) {
583        if (theConverter == null) initConverter();
584        return theConverter.printQName( val, nsc );
585    }
586
587    /**
588     * <p>
589     * Converts a Calendar value into a string.
590     * @param val
591     *     A Calendar value
592     * @return
593     *     A string containing a lexical representation of xsd:dateTime
594     * @throws IllegalArgumentException if {@code val} is null.
595     */
596    public static String printDateTime( java.util.Calendar val ) {
597        if (theConverter == null) initConverter();
598        return theConverter.printDateTime( val );
599    }
600
601    /**
602     * <p>
603     * Converts an array of bytes into a string.
604     * @param val
605     *     An array of bytes
606     * @return
607     *     A string containing a lexical representation of xsd:base64Binary
608     * @throws IllegalArgumentException if {@code val} is null.
609     */
610    public static String printBase64Binary( byte[] val ) {
611        if (theConverter == null) initConverter();
612        return theConverter.printBase64Binary( val );
613    }
614
615    /**
616     * <p>
617     * Converts an array of bytes into a string.
618     * @param val
619     *     An array of bytes
620     * @return
621     *     A string containing a lexical representation of xsd:hexBinary
622     * @throws IllegalArgumentException if {@code val} is null.
623     */
624    public static String printHexBinary( byte[] val ) {
625        if (theConverter == null) initConverter();
626        return theConverter.printHexBinary( val );
627    }
628
629    /**
630     * <p>
631     * Converts a long value into a string.
632     * @param val
633     *     A long value
634     * @return
635     *     A string containing a lexical representation of xsd:unsignedInt
636     */
637    public static String printUnsignedInt( long val ) {
638        if (theConverter == null) initConverter();
639        return theConverter.printUnsignedInt( val );
640    }
641
642    /**
643     * <p>
644     * Converts an int value into a string.
645     * @param val
646     *     An int value
647     * @return
648     *     A string containing a lexical representation of xsd:unsignedShort
649     */
650    public static String printUnsignedShort( int val ) {
651        if (theConverter == null) initConverter();
652        return theConverter.printUnsignedShort( val );
653    }
654
655    /**
656     * <p>
657     * Converts a Calendar value into a string.
658     * @param val
659     *     A Calendar value
660     * @return
661     *     A string containing a lexical representation of xsd:time
662     * @throws IllegalArgumentException if {@code val} is null.
663     */
664    public static String printTime( java.util.Calendar val ) {
665        if (theConverter == null) initConverter();
666        return theConverter.printTime( val );
667    }
668
669    /**
670     * <p>
671     * Converts a Calendar value into a string.
672     * @param val
673     *     A Calendar value
674     * @return
675     *     A string containing a lexical representation of xsd:date
676     * @throws IllegalArgumentException if {@code val} is null.
677     */
678    public static String printDate( java.util.Calendar val ) {
679        if (theConverter == null) initConverter();
680        return theConverter.printDate( val );
681    }
682
683    /**
684     * <p>
685     * Converts a string value into a string.
686     * @param val
687     *     A string value
688     * @return
689     *     A string containing a lexical representation of xsd:AnySimpleType
690     */
691    public static String printAnySimpleType( String val ) {
692        if (theConverter == null) initConverter();
693        return theConverter.printAnySimpleType( val );
694    }
695}
696