1 /*
2  * Copyright (c) 2003, 2018 Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Distribution License v. 1.0, which is available at
6  * http://www.eclipse.org/org/documents/edl-v10.php.
7  *
8  * SPDX-License-Identifier: BSD-3-Clause
9  */

10
11 package javax.xml.bind;
12
13 import javax.xml.namespace.NamespaceContext;
14
15 /**
16  * <p>
17  * The javaType binding declaration can be used to customize the binding of 
18  * an XML schema datatype to a Java datatype. Customizations can involve 
19  * writing a parse and print method for parsing and printing lexical 
20  * representations of a XML schema datatype respectively. However, writing 
21  * parse and print methods requires knowledge of the lexical representations ( 
22  * <a href="http://www.w3.org/TR/xmlschema-2/"> XML Schema Part2: Datatypes 
23  * specification </a>) and hence may be difficult to write. 
24  * </p>
25  * <p>
26  * This class makes it easier to write parse and print methods. It defines
27  * static parse and print methods that provide access to a JAXB provider's 
28  * implementation of parse and print methods. These methods are invoked by 
29  * custom parse and print methods. For example, the binding of xsd:dateTime 
30  * to a long can be customized using parse and print methods as follows:
31  * <blockquote>
32  *    <pre>
33  *    // Customized parse method 
34  *    public long myParseCal( String dateTimeString ) {
35  *        java.util.Calendar cal = DatatypeConverter.parseDateTime(dateTimeString);
36  *        long longval = convert_calendar_to_long(cal); //application specific
37  *        return longval;
38  *    }
39  *     
40  *    // Customized print method
41  *    public String myPrintCal( Long longval ) {
42  *        java.util.Calendar cal = convert_long_to_calendar(longval) ; //application specific
43  *        String dateTimeString = DatatypeConverter.printDateTime(cal);
44  *        return dateTimeString;
45  *    }
46  *    </pre>
47  * </blockquote>
48  * <p>
49  * There is a static parse and print method corresponding to each parse and 
50  * print method respectively in the {@link DatatypeConverterInterface 
51  * DatatypeConverterInterface}. 
52  * <p>
53  * The static methods defined in the class can also be used to specify
54  * a parse or a print method in a javaType binding declaration.
55  * </p>
56  * <p>
57  * JAXB Providers are required to call the 
58  * {@link #setDatatypeConverter(DatatypeConverterInterface) 
59  * setDatatypeConverter} api at some point before the first marshal or unmarshal 
60  * operation (perhaps during the call to JAXBContext.newInstance).  This step is 
61  * necessary to configure the converter that should be used to perform the 
62  * print and parse functionality.  
63  * </p>
64  * 
65  * <p>
66  * A print method for a XML schema datatype can output any lexical 
67  * representation that is valid with respect to the XML schema datatype.
68  * If an error is encountered during conversion, then an IllegalArgumentException,
69  * or a subclass of IllegalArgumentException must be thrown by the method.
70  * </p>
71  * 
72  * @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>
73  * @see DatatypeConverterInterface
74  * @see ParseConversionEvent
75  * @see PrintConversionEvent
76  * @since 1.6, JAXB 1.0
77  */

78
79 final public class DatatypeConverter {
80
81     // delegate to this instance of DatatypeConverter
82     private static volatile DatatypeConverterInterface theConverter = null;
83
84     private final static JAXBPermission SET_DATATYPE_CONVERTER_PERMISSION =
85                            new JAXBPermission("setDatatypeConverter");
86
87     private DatatypeConverter() {
88         // private constructor
89     }
90     
91     /**
92      * This method is for JAXB provider use only.
93      * <p>
94      * JAXB Providers are required to call this method at some point before
95      * allowing any of the JAXB client marshal or unmarshal operations to
96      * occur.  This is necessary to configure the datatype converter that 
97      * should be used to perform the print and parse conversions.
98      * 
99      * <p>
100      * Calling this api repeatedly will have no effect - the 
101      * DatatypeConverterInterface instance passed into the first invocation is 
102      * the one that will be used from then on.
103      * 
104      * @param converter an instance of a class that implements the 
105      * DatatypeConverterInterface class - this parameter must not be null.
106      * @throws IllegalArgumentException if the parameter is null
107      * @throws SecurityException
108      *      If the {@link SecurityManager} in charge denies the access to
109      *      set the datatype converter. 
110      * @see JAXBPermission
111      */

112     public static void setDatatypeConverter( DatatypeConverterInterface converter ) {
113         if( converter == null ) {
114             throw new IllegalArgumentException( 
115                 Messages.format( Messages.CONVERTER_MUST_NOT_BE_NULL ) );
116         } else if( theConverter == null ) {
117             SecurityManager sm = System.getSecurityManager();
118             if (sm != null)
119                 sm.checkPermission(SET_DATATYPE_CONVERTER_PERMISSION);
120             theConverter = converter;
121         }
122     }
123
124     private static synchronized void initConverter() {
125         theConverter = new DatatypeConverterImpl();
126     }
127     
128     /**
129      * <p>
130      * Convert the lexical XSD string argument into a String value.
131      * @param lexicalXSDString
132      *     A string containing a lexical representation of
133      *     xsd:string.
134      * @return
135      *     A String value represented by the string argument.
136      */
 
137     public static String parseString( String lexicalXSDString ) {
138         if (theConverter == null) initConverter();
139         return theConverter.parseString( lexicalXSDString );
140     }
141
142     /**
143      * <p>
144      * Convert the string argument into a BigInteger value.
145      * @param lexicalXSDInteger
146      *     A string containing a lexical representation of
147      *     xsd:integer.
148      * @return
149      *     A BigInteger value represented by the string argument.
150      * @throws NumberFormatException <code>lexicalXSDInteger</code> is not a valid string representation of a {@link java.math.BigInteger} value.
151      */
 
152     public static java.math.BigInteger parseInteger( String lexicalXSDInteger ) {
153         if (theConverter == null) initConverter();
154         return theConverter.parseInteger( lexicalXSDInteger );
155     }
156
157     /**
158      * <p>
159      * Convert the string argument into an int value.
160      * @param lexicalXSDInt
161      *     A string containing a lexical representation of
162      *     xsd:int.
163      * @return
164      *     A int value represented by the string argument.
165      * @throws NumberFormatException <code>lexicalXSDInt</code> is not a valid string representation of an <code>int</code> value.
166      */
 
167     public static int parseInt( String lexicalXSDInt ) {
168         if (theConverter == null) initConverter();
169         return theConverter.parseInt( lexicalXSDInt );
170     }
171
172     /**
173      * <p>
174      * Converts the string argument into a long value.
175      * @param lexicalXSDLong
176      *     A string containing lexical representation of
177      *     xsd:long.
178      * @return
179      *     A long value represented by the string argument.
180      * @throws NumberFormatException <code>lexicalXSDLong</code> is not a valid string representation of a <code>long</code> value.
181      */
 
182     public static long parseLong( String lexicalXSDLong ) {
183         if (theConverter == null) initConverter();
184         return theConverter.parseLong( lexicalXSDLong );
185     }
186
187     /**
188      * <p>
189      * Converts the string argument into a short value.
190      * @param lexicalXSDShort
191      *     A string containing lexical representation of
192      *     xsd:short.
193      * @return
194      *     A short value represented by the string argument.
195      * @throws NumberFormatException <code>lexicalXSDShort</code> is not a valid string representation of a <code>short</code> value.
196      */
 
197     public static short parseShort( String lexicalXSDShort ) { 
198         if (theConverter == null) initConverter();
199         return theConverter.parseShort( lexicalXSDShort );
200     }
201
202     /**
203      * <p>
204      * Converts the string argument into a BigDecimal value.
205      * @param lexicalXSDDecimal
206      *     A string containing lexical representation of
207      *     xsd:decimal.
208      * @return
209      *     A BigDecimal value represented by the string argument.
210      * @throws NumberFormatException <code>lexicalXSDDecimal</code> is not a valid string representation of {@link java.math.BigDecimal}.
211      */
 
212     public static java.math.BigDecimal parseDecimal( String lexicalXSDDecimal ) {
213         if (theConverter == null) initConverter();
214         return theConverter.parseDecimal( lexicalXSDDecimal );
215     }
216
217     /**
218      * <p>
219      * Converts the string argument into a float value.
220      * @param lexicalXSDFloat
221      *     A string containing lexical representation of
222      *     xsd:float.
223      * @return
224      *     A float value represented by the string argument.
225      * @throws NumberFormatException <code>lexicalXSDFloat</code> is not a valid string representation of a <code>float</code> value.
226      */
 
227     public static float parseFloat( String lexicalXSDFloat ) {
228         if (theConverter == null) initConverter();
229         return theConverter.parseFloat( lexicalXSDFloat );
230     }
231
232     /**
233      * <p>
234      * Converts the string argument into a double value.
235      * @param lexicalXSDDouble
236      *     A string containing lexical representation of
237      *     xsd:double.
238      * @return
239      *     A double value represented by the string argument.
240      * @throws NumberFormatException <code>lexicalXSDDouble</code> is not a valid string representation of a <code>double</code> value.
241      */
 
242     public static double parseDouble( String lexicalXSDDouble ) { 
243         if (theConverter == null) initConverter();
244         return theConverter.parseDouble( lexicalXSDDouble );
245     }
246
247     /**
248      * <p>
249      * Converts the string argument into a boolean value.
250      * @param lexicalXSDBoolean
251      *     A string containing lexical representation of
252      *     xsd:boolean.
253      * @return
254      *     A boolean value represented by the string argument.
255      * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:boolean.
256      */
 
257     public static boolean parseBoolean( String lexicalXSDBoolean ) {
258         if (theConverter == null) initConverter();
259         return theConverter.parseBoolean( lexicalXSDBoolean );
260     }
261
262     /**
263      * <p>
264      * Converts the string argument into a byte value.
265      * @param lexicalXSDByte
266      *     A string containing lexical representation of
267      *     xsd:byte.
268      * @return
269      *     A byte 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:byte.
271      */
 
272     public static byte parseByte( String lexicalXSDByte ) { 
273         if (theConverter == null) initConverter();
274         return theConverter.parseByte( lexicalXSDByte );
275     }
276
277     /**
278      * <p>
279      * Converts the string argument into a byte value.
280      *
281      * <p>
282      * String parameter {@code lexicalXSDQname} must conform to lexical value space specifed at
283      * <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part 2:Datatypes specification:QNames</a>
284      * 
285      * @param lexicalXSDQName
286      *     A string containing lexical representation of xsd:QName.
287      * @param nsc
288      *     A namespace context for interpreting a prefix within a QName.
289      * @return
290      *     A QName value represented by the string argument.
291      * @throws IllegalArgumentException  if string parameter does not conform to XML Schema Part 2 specification or 
292      *      if namespace prefix of {@code lexicalXSDQname} is not bound to a URI in NamespaceContext {@code nsc}.
293      */
 
294     public static javax.xml.namespace.QName parseQName( String lexicalXSDQName,
295                                         NamespaceContext nsc) {
296         if (theConverter == null) initConverter();
297         return theConverter.parseQName( lexicalXSDQName, nsc );
298     }
299
300     /**
301      * <p>
302      * Converts the string argument into a Calendar value.
303      * @param lexicalXSDDateTime
304      *     A string containing lexical representation of
305      *     xsd:datetime.
306      * @return
307      *     A Calendar object represented by the string argument.
308      * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:dateTime.
309      */
 
310     public static java.util.Calendar parseDateTime( String lexicalXSDDateTime ) {
311         if (theConverter == null) initConverter();
312         return theConverter.parseDateTime( lexicalXSDDateTime );
313     }
314
315     /**
316      * <p>
317      * Converts the string argument into an array of bytes.
318      * @param lexicalXSDBase64Binary
319      *     A string containing lexical representation
320      *     of xsd:base64Binary.
321      * @return
322      *     An array of bytes 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:base64Binary
324      */
 
325     public static byte[] parseBase64Binary( String lexicalXSDBase64Binary ) {
326         if (theConverter == null) initConverter();
327         return theConverter.parseBase64Binary( lexicalXSDBase64Binary );
328     }
329
330     /**
331      * <p>
332      * Converts the string argument into an array of bytes.
333      * @param lexicalXSDHexBinary
334      *     A string containing lexical representation of
335      *     xsd:hexBinary.
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:hexBinary.
339      */
 
340    public static byte[] parseHexBinary( String lexicalXSDHexBinary ) {
341         if (theConverter == null) initConverter();
342         return theConverter.parseHexBinary( lexicalXSDHexBinary );
343     }
344
345     /**
346      * <p>
347      * Converts the string argument into a long value.
348      * @param lexicalXSDUnsignedInt
349      *     A string containing lexical representation
350      *     of xsd:unsignedInt.
351      * @return
352      *     A long value represented by the string argument.
353      * @throws NumberFormatException if string parameter can not be parsed into a {@code long} value.
354      */
 
355     public static long parseUnsignedInt( String lexicalXSDUnsignedInt ) {
356         if (theConverter == null) initConverter();
357         return theConverter.parseUnsignedInt( lexicalXSDUnsignedInt );
358     }
359
360     /**
361      * <p>
362      * Converts the string argument into an int value.
363      * @param lexicalXSDUnsignedShort
364      *     A string containing lexical
365      *     representation of xsd:unsignedShort.
366      * @return
367      *     An int value represented by the string argument.
368      * @throws NumberFormatException if string parameter can not be parsed into an {@code int} value.
369      */
 
370     public static int    parseUnsignedShort( String lexicalXSDUnsignedShort ) {
371         if (theConverter == null) initConverter();
372         return theConverter.parseUnsignedShort( lexicalXSDUnsignedShort );
373     }
374
375     /**
376      * <p>
377      * Converts the string argument into a Calendar value.
378      * @param lexicalXSDTime
379      *     A string containing lexical representation of
380      *     xsd:time.
381      * @return
382      *     A Calendar value represented by the string argument.
383      * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:Time.
384      */
 
385     public static java.util.Calendar parseTime( String lexicalXSDTime ) {
386         if (theConverter == null) initConverter();
387         return theConverter.parseTime( lexicalXSDTime ); 
388     }
389     /**
390      * <p>
391      * Converts the string argument into a Calendar value.
392      * @param lexicalXSDDate
393      *      A string containing lexical representation of
394      *     xsd:Date.
395      * @return
396      *     A Calendar value represented by the string argument.
397      * @throws IllegalArgumentException if string parameter does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:Date.
398      */
 
399     public static java.util.Calendar parseDate( String lexicalXSDDate ) {
400         if (theConverter == null) initConverter();
401         return theConverter.parseDate( lexicalXSDDate );
402     }
403
404     /**
405      * <p>
406      * Return a string containing the lexical representation of the 
407      * simple type.
408      * @param lexicalXSDAnySimpleType
409      *     A string containing lexical
410      *     representation of the simple type.
411      * @return
412      *     A string containing the lexical representation of the 
413      *     simple type.
414      */
 
415     public static String parseAnySimpleType( String lexicalXSDAnySimpleType ) {
416         if (theConverter == null) initConverter();
417         return theConverter.parseAnySimpleType( lexicalXSDAnySimpleType );
418     }
419     /**
420      * <p>
421      * Converts the string argument into a string.
422      * @param val
423      *     A string value.
424      * @return
425      *     A string containing a lexical representation of xsd:string.
426      */
 
427      // also indicate the print methods produce a lexical
428      // representation for given Java datatypes.
429     
430     public static String printString( String val ) {
431         if (theConverter == null) initConverter();
432         return theConverter.printString( val );
433     }
434
435     /**
436      * <p>
437      * Converts a BigInteger value into a string.
438      * @param val
439      *     A BigInteger value
440      * @return
441      *     A string containing a lexical representation of xsd:integer
442      * @throws IllegalArgumentException {@code val} is null.
443      */
 
444     public static String printInteger( java.math.BigInteger val ) {
445         if (theConverter == null) initConverter();
446         return theConverter.printInteger( val );
447     }
448
449     /**
450      * <p>
451      * Converts an int value into a string.
452      * @param val
453      *     An int value
454      * @return
455      *     A string containing a lexical representation of xsd:int
456      */
 
457     public static String printInt( int val ) {
458         if (theConverter == null) initConverter();
459         return theConverter.printInt( val );
460     }
461
462     /**
463      * <p>
464      * Converts A long value into a string.
465      * @param val
466      *     A long value
467      * @return
468      *     A string containing a lexical representation of xsd:long
469      */
 
470     public static String printLong( long val ) {
471         if (theConverter == null) initConverter();
472         return theConverter.printLong( val );
473     }
474
475     /**
476      * <p>
477      * Converts a short value into a string.
478      * @param val
479      *     A short value
480      * @return
481      *     A string containing a lexical representation of xsd:short
482      */
 
483     public static String printShort( short val ) {
484         if (theConverter == null) initConverter();
485         return theConverter.printShort( val );
486     }
487
488     /**
489      * <p>
490      * Converts a BigDecimal value into a string.
491      * @param val
492      *     A BigDecimal value
493      * @return
494      *     A string containing a lexical representation of xsd:decimal
495      * @throws IllegalArgumentException {@code val} is null.
496      */
 
497     public static String printDecimal( java.math.BigDecimal val ) {
498         if (theConverter == null) initConverter();
499         return theConverter.printDecimal( val );
500     }
501
502     /**
503      * <p>
504      * Converts a float value into a string.
505      * @param val
506      *     A float value
507      * @return
508      *     A string containing a lexical representation of xsd:float
509      */
 
510     public static String printFloat( float val ) {
511         if (theConverter == null) initConverter();
512         return theConverter.printFloat( val );
513     }
514
515     /**
516      * <p>
517      * Converts a double value into a string.
518      * @param val
519      *     A double value
520      * @return
521      *     A string containing a lexical representation of xsd:double
522      */
 
523     public static String printDouble( double val ) {
524         if (theConverter == null) initConverter();
525         return theConverter.printDouble( val );
526     }
527
528     /**
529      * <p>
530      * Converts a boolean value into a string.
531      * @param val
532      *     A boolean value
533      * @return
534      *     A string containing a lexical representation of xsd:boolean
535      */
 
536     public static String printBoolean( boolean val ) {
537         if (theConverter == null) initConverter();
538         return theConverter.printBoolean( val );
539     }
540
541     /**
542      * <p>
543      * Converts a byte value into a string.
544      * @param val
545      *     A byte value
546      * @return
547      *     A string containing a lexical representation of xsd:byte
548      */
 
549     public static String printByte( byte val ) {
550         if (theConverter == null) initConverter();
551         return theConverter.printByte( val );
552     }
553
554     /**
555      * <p>
556      * Converts a QName instance into a string.
557      * @param val
558      *     A QName value
559      * @param nsc
560      *     A namespace context for interpreting a prefix within a QName.
561      * @return
562      *     A string containing a lexical representation of QName
563      * @throws IllegalArgumentException if {@code val} is null or
564      * if {@code nsc} is non-null or {@code nsc.getPrefix(nsprefixFromVal)} is null.
565      */
 
566     public static String printQName( javax.xml.namespace.QName val,
567                                      NamespaceContext nsc ) {
568         if (theConverter == null) initConverter();
569         return theConverter.printQName( val, nsc );
570     }
571
572     /**
573      * <p>
574      * Converts a Calendar value into a string.
575      * @param val
576      *     A Calendar value
577      * @return
578      *     A string containing a lexical representation of xsd:dateTime
579      * @throws IllegalArgumentException if {@code val} is null.
580      */
 
581     public static String printDateTime( java.util.Calendar val ) {
582         if (theConverter == null) initConverter();
583         return theConverter.printDateTime( val );
584     }
585
586     /**
587      * <p>
588      * Converts an array of bytes into a string.
589      * @param val
590      *     An array of bytes
591      * @return
592      *     A string containing a lexical representation of xsd:base64Binary
593      * @throws IllegalArgumentException if {@code val} is null.
594      */
 
595     public static String printBase64Binary( byte[] val ) {
596         if (theConverter == null) initConverter();
597         return theConverter.printBase64Binary( val );
598     }
599
600     /**
601      * <p>
602      * Converts an array of bytes into a string.
603      * @param val
604      *     An array of bytes
605      * @return
606      *     A string containing a lexical representation of xsd:hexBinary
607      * @throws IllegalArgumentException if {@code val} is null.
608      */
 
609     public static String printHexBinary( byte[] val ) {
610         if (theConverter == null) initConverter();
611         return theConverter.printHexBinary( val );
612     }
613
614     /**
615      * <p>
616      * Converts a long value into a string.
617      * @param val
618      *     A long value
619      * @return
620      *     A string containing a lexical representation of xsd:unsignedInt
621      */
 
622     public static String printUnsignedInt( long val ) {
623         if (theConverter == null) initConverter();
624         return theConverter.printUnsignedInt( val );
625     }
626
627     /**
628      * <p>
629      * Converts an int value into a string.
630      * @param val
631      *     An int value
632      * @return
633      *     A string containing a lexical representation of xsd:unsignedShort
634      */
 
635     public static String printUnsignedShort( int val ) {
636         if (theConverter == null) initConverter();
637         return theConverter.printUnsignedShort( val );
638     }
639
640     /**
641      * <p>
642      * Converts a Calendar value into a string.
643      * @param val
644      *     A Calendar value
645      * @return
646      *     A string containing a lexical representation of xsd:time
647      * @throws IllegalArgumentException if {@code val} is null.
648      */
 
649     public static String printTime( java.util.Calendar val ) {
650         if (theConverter == null) initConverter();
651         return theConverter.printTime( val );
652     }
653
654     /**
655      * <p>
656      * Converts a Calendar value into a string.
657      * @param val
658      *     A Calendar value
659      * @return
660      *     A string containing a lexical representation of xsd:date
661      * @throws IllegalArgumentException if {@code val} is null.
662      */
 
663     public static String printDate( java.util.Calendar val ) {
664         if (theConverter == null) initConverter();
665         return theConverter.printDate( val );
666     }
667
668     /**
669      * <p>
670      * Converts a string value into a string.
671      * @param val
672      *     A string value
673      * @return
674      *     A string containing a lexical representation of xsd:AnySimpleType
675      */
 
676     public static String printAnySimpleType( String val ) {
677         if (theConverter == null) initConverter();
678         return theConverter.printAnySimpleType( val );
679     }
680 }
681