001    /*
002     * Copyright 2002,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.scaffold.text;
018    
019    import java.text.DateFormat;
020    import java.text.DecimalFormat;
021    import java.text.DecimalFormatSymbols;
022    import java.text.NumberFormat;
023    import java.text.ParseException;
024    import java.text.SimpleDateFormat;
025    
026    import java.util.Date;
027    import java.util.Iterator;
028    import java.util.List;
029    import java.util.Locale;
030    import java.util.Map;
031    import java.util.Map.Entry;
032    import java.util.Set;
033    import java.util.StringTokenizer;
034    
035    import java.sql.Timestamp;
036    
037    /**
038     * An <b>experimental</b> class with some standard conversion
039     * utilities. Needs more proof of concept and unit testing.
040     *
041     * @author Ted Husted
042     * @author OK State DEQ
043     * @author WXXI Public Broadcasting Council
044     * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $
045     */
046    public class ConvertUtils {
047    
048    /*
049        protected Locale[] availableLocales = null;
050        public static Locale[] getAvailableLocales() {
051            return availableLocales;
052        }
053        public static void setAvailableLocales(Locale[] _availableLocales) {
054            availableLocales = _availableLocales;
055        }
056    
057    */
058    
059    
060        /**
061         * This is an all-static utility class.
062         * A private constructor prevents inadvertent instantiation.
063         */
064        private ConvertUtils() { 
065            ; // empty 
066        }
067    
068    
069    // ---------------------------------------------------- Text Separators
070    
071        /**
072         * An empty string.
073         */
074        public static String STRING_EMPTY = "";
075    
076    
077        /**
078         * An empty string.
079         * @deprecated Use STRING_EMPTY
080         */
081        public static String EMPTY_STRING = STRING_EMPTY;
082    
083    
084        /**
085         * An single-space string.
086         */
087        public static final String STRING_SPACE = " ";
088    
089    
090        /**
091         * Space character.
092         */
093        public static final char SPACE                 = ' ';
094    
095    
096        /**
097         * Horizontal tab character.
098         */
099        public static final char HORIZONTAL_TABULATION = '\t';     // (aka u0009)
100    
101    
102        /**
103         * Line feed character.
104         */
105        public static final char LINE_FEED             = '\r';     // (aka u000A);
106    
107    
108        /**
109         * Vertical tab character.
110         */
111        public static final char VERTICAL_TABULATION   = '\u000B';
112    
113    
114        /**
115         * Form feed character.
116         */
117        public static final char FORM_FEED             = '\u000C';
118    
119    
120        /**
121         * Carriage return character.
122         */
123        public static final char CARRIAGE_RETURN       = '\n';     // (aka u000D)
124    
125    
126        /**
127         * File separator character.
128         */
129        public static final char FILE_SEPARATOR        = '\u001C';
130    
131    
132        /**
133         * Group separator character.
134         */
135        public static final char GROUP_SEPARATOR       = '\u001D';
136    
137    
138        /**
139         * Record separator character.
140         */
141        public static final char RECORD_SEPARATOR      = '\u001E';
142    
143    
144        /**
145         * Unit separator character.
146         */
147        public static final char UNIT_SEPARATOR        = '\u001F';
148    
149    
150        /**
151         * Array of line separator characters.
152         * http://java.sun.com/j2se/1.3/docs/api/java/lang/Character.html#isWhitespace(char)
153         */
154        public static final char[] SEPARATORS = {
155                HORIZONTAL_TABULATION,
156                LINE_FEED,
157                VERTICAL_TABULATION,
158                FORM_FEED,
159                CARRIAGE_RETURN,
160                FILE_SEPARATOR,
161                GROUP_SEPARATOR,
162                RECORD_SEPARATOR,
163                UNIT_SEPARATOR
164            };
165    
166    // --------------------------------------------------------- Tokenizers
167    
168    
169        /**
170         * Return array of tokens,
171         * using the result of <code>getTokeSep()</code> as the
172         * separator.
173         * Blanks are trimmed from tokens.
174         *
175         * @param parameter The string to tokenize into an array
176         */
177        public static String[] tokensToArray(String tokens, String separator) {
178    
179            StringTokenizer tokenizer =
180                new StringTokenizer(tokens,separator);
181            int i = 0;
182            String[] array = new String[tokenizer.countTokens()];
183            while (tokenizer.hasMoreTokens()) {
184                String token = tokenizer.nextToken().trim();
185                if ((token==null) || (token.length()==0)) continue;
186                array[i++] = token;
187            }
188            return array;
189            
190        } // end tokensToArray
191        
192    
193        /**
194         * Return list of tokens,
195         * using the result of <code>getTokeSep()</code> as the
196         * separator.
197         * Blanks are trimmed from tokens.
198         *
199         * @param parameter The string to tokenize into an array
200         */
201        public static List tokensToList(String tokens, String separator) {
202    
203            StringTokenizer tokenizer =
204                new StringTokenizer(tokens,separator);
205            List list = new java.util.ArrayList(tokenizer.countTokens());
206            while (tokenizer.hasMoreTokens()) {
207                String token = tokenizer.nextToken().trim();
208                if ((token==null) || (token.length()==0)) continue;
209                list.add(token);
210            }
211            return list;
212            
213        } // end tokensToList
214        
215    
216    // ------------------------------------------------------- Text Methods
217    
218    
219        /**
220         * Returns true if null or trims to an empty string.
221         * @deprecated Use blank instead.
222         */
223        public static boolean isBlank(String s) {
224            return blank(s);
225        }
226    
227    
228        /**
229         * Returns true if null or zero.
230         * @deprecated Use blank instead.
231         */
232        public static boolean isBlank(Integer key) {
233          return blank(key);
234        }
235    
236    
237        /**
238         * Returns true if null or trims to an empty string.
239         * @deprecated Use blankValue instead.
240         */
241        public static boolean isBlankValue(String s) {
242            return blankValue(s);
243        }
244    
245    
246        /**
247         * Returns true if null or trims to an empty string.
248         * @deprecated Use blank instead.
249         */
250        public static boolean blank(String s) {
251            return ((null==s) || (STRING_EMPTY.equals(s.trim())));
252        }
253    
254    
255        /**
256         * Returns true if null or zero.
257         * @deprecated Use blank instead.
258         */
259        public static boolean blank(Number key) {
260          return ((null==key) || (0==key.byteValue()));
261        }
262    
263    
264        /**
265         * Returns true if null, trims to an empty string,
266         * or to "0".
267         */
268        public static boolean blankValue(String s) {
269            if (null==s) return true;
270            String _s = s.trim();
271            return ((STRING_EMPTY.equals(_s)) || (STRING_ZERO.equals(_s)));
272        }
273    
274    
275        /**
276         * Return a trimmed or empty string (but not null).
277         */
278        public static String toTrimOrEmpty(String string) {
279            if (null==string) return STRING_EMPTY; 
280            return string.trim();
281        }
282    
283    
284        /**
285         * Returns null or a trimmed uppercase string.
286         */
287        public static String toUpperOrNull(String string) {
288            if (null!=string)
289                return string.toUpperCase().trim();
290            return null;
291        }
292    
293    
294        /**
295         * The token that signifies the begnning of a query string ["?"].
296         */
297        public static String QS_START = "?";
298    
299    
300        /**
301         * The token that delimits two or more attributes of a query string ["&amp;"].
302         */
303        public static String QS_DELIM = "&amp;";
304    
305    
306        /**
307         * The token that seperates an attribute name and value.
308         */
309        public static String QS_SEP = "=";
310    
311    
312        /**
313         * Appends name=value parameter.
314         */
315        public static String addParam(String path, String name, String value) {
316            StringBuffer uri = new StringBuffer(path);
317            boolean isQuery = (path.indexOf(QS_START)>=0);
318            if (isQuery)
319                uri.append(QS_DELIM);
320            else
321                uri.append(QS_START);
322            uri.append(name);
323            uri.append(QS_SEP);
324            uri.append(value);
325            return uri.toString();
326    
327         }
328    
329    
330        /**
331         * Appends name=value parameters to path from Map.
332         */
333        public static String addParams(String path, Map parameters) {
334    
335            if (null==path) path = new String();
336    
337            if ((null==parameters) || (parameters.isEmpty())) return path;
338    
339            StringBuffer uri = new StringBuffer(path);
340            boolean isQuery = (path.indexOf(QS_START)>=0);
341            if (isQuery)
342                uri.append(QS_DELIM);
343            else
344                uri.append(QS_START);
345    
346            Set entries = parameters.entrySet();
347            for (Iterator i = entries.iterator(); i.hasNext(); ) {
348                Entry e = (Entry) i.next();
349                uri.append(e.getKey());
350                uri.append(QS_SEP);
351                uri.append(e.getValue());
352            }
353            return uri.toString();
354    
355         }
356    
357    
358        /**
359         * Returns parameters as a series of hidden HTML fields.
360         */
361        public static String renderHiddenFields(Map parameters) {
362    
363            if ((null==parameters) || (parameters.isEmpty())) return new String();
364    
365            StringBuffer html = new StringBuffer();
366            Set entries = parameters.entrySet();
367            for (Iterator i = entries.iterator(); i.hasNext(); ) {
368                html.append("<input type='hidden' name='");
369                Entry e = (Entry) i.next();
370                html.append(e.getKey());
371                html.append("' value='");
372                html.append(e.getValue());
373                html.append("' />");
374            }
375            return html.toString();
376    
377         }
378    
379    
380        /**
381         * Replace line returns with spaces.
382         */
383        private static String stripLn(String string) {
384    
385            // :FIXME: Better way to buffer the interim strings?
386            for (int i=0; i<SEPARATORS.length; i++) {
387               string = string.replace(
388                    SEPARATORS[i],
389                    SPACE
390                );
391            }
392            return string;
393        }
394    
395    
396    
397    // ----------------------------------------------------- Numeric Values
398    
399    
400        /**
401         * An Double 0.
402         */
403        public static Double DOUBLE_ZERO = new Double(0);
404    
405    
406        /**
407         * An Double 1.
408         */
409        public static Double DOUBLE_ONE = new Double((double) 1.0);
410    
411    
412        /**
413         * An Integer 0.
414         */
415        public static Integer INTEGER_ZERO = new Integer(0);
416    
417    
418        /**
419         * An Integer 1.
420         */
421        public static Integer INTEGER_ONE = new Integer(1);
422    
423    
424        /**
425         * A Short 0.
426         */
427        public static Short SHORT_ZERO = new Short((short) 0);
428    
429    
430        /**
431         * A Short 1.
432         */
433        public static Short SHORT_ONE = new Short((short) 1);
434    
435    
436        /**
437         * A String 0.
438         */
439        public static String STRING_ZERO = "0";
440    
441    
442        /**
443         * A String 1.
444         */
445        public static String STRING_ONE = "1";
446    
447    
448    
449    
450    // ---------------------------------------------------- Numeric Methods
451    
452    
453        /**
454         * Return String with of digits only (0..9).
455         * http://java.sun.com/j2se/1.4/docs/api/java/lang/Character.html
456         */
457        public static String getDigits(String s) {
458            if (s==null) return null;
459            int n = s.length();
460            StringBuffer sb = new StringBuffer(n);
461            for (int i = 0; i < n; i++) {
462                char c = s.charAt(i);
463                if (Character.isDigit(c)) sb.append(c);
464            }
465            return (sb.toString());
466        }
467    
468    
469        /**
470         * Returns number formatted for default or given locale.
471         */
472        public static String getNumber(Number value, Locale locale) {
473            if (locale==null)
474                return (NumberFormat.getInstance().format(value));
475           return (NumberFormat.getInstance(locale).format(value));
476        }
477    
478    
479        /**
480         * Returns percent formatted for default or given locale.
481         */
482        public static String getPercent(Number value, Locale locale) {
483            if (locale==null)
484                return (NumberFormat.getPercentInstance().format(value));
485            return (NumberFormat.getPercentInstance(locale).format(value));
486        }
487    
488    
489        /* -- Is there a use case for this?
490    
491        public static String getInteger(Number value, Locale locale) {
492            if (locale==null)
493                return (NumberFormat.getIntegerInstance().format(value));
494            return (NumberFormat.getIntegerInstance(locale).format(value));
495        }
496    
497        */
498    
499    
500        /*
501         * Returns whether the last digit of numeric string is a parity
502         * check on the others per the "primes of nines" method.
503         * Reference: http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl
504         * @param Number - Number to check.
505         * Must be all digits and not null.
506         */
507        public static boolean luhnCheck(String number) {
508            int no_digit = number.length();
509            int oddoeven = no_digit & 1;
510            long sum = 0;
511            for (int count = 0; count < no_digit; count++) {
512                int digit = Integer.parseInt(
513                    String.valueOf(number.charAt(count)));
514                if ( ( (count & 1) ^ oddoeven) ==0 ) { // not
515                    digit *= 2;
516                    if (digit > 9) digit -= 9;
517                };
518                sum += digit;
519            };
520            if (sum == 0) return false;
521            if (sum % 10 == 0) return true;
522            return false;
523        }
524    
525    
526        /**
527         * Returns number with the appropriate digit appended
528         * so that is passes a "luhnCheck".
529         * @param Number - Number to process.
530         * Must be all digits and not null.
531         */
532        public static String addLuhnDigit(String number) {
533            // I don't actually understand the alogorithm
534            // so we just use brute force to find the digit.
535            char[] digits = {'1','2','3','4','5','6','7','8','9','0'};
536            int c = number.length();
537            StringBuffer tryNumber = new StringBuffer(number + digits[0]);
538            int i;
539            for (i=0; i<10; i++) {
540                tryNumber.setCharAt(c,digits[i]);
541                if (luhnCheck(tryNumber.toString()))
542                    break;
543            }
544            return tryNumber.toString();
545        }
546    
547    
548    // ------------------------------------------------------------ Decimal
549    
550    
551        /**
552         * Default decimal pattern.
553         * http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
554         */
555        public static String DECIMAL_PATTERN ="###,###.###";
556    
557    
558        /**
559         * Symbols that can be used in a decimal pattern.
560         */
561        public static DecimalFormatSymbols getGenericDecimal(Locale locale) {
562            DecimalFormatSymbols symbols =
563                new DecimalFormatSymbols(locale);
564            symbols.setGroupingSeparator('`'); // :FIXME: Want apostrophe here
565            return symbols;
566        }
567    
568    
569        /**
570         * Return decimal number formatted for default or given locale.
571         */
572        public static String getDecimal(Number value, Locale locale) {
573            if (locale==null)
574                return (DecimalFormat.getInstance().format(value));
575            return (DecimalFormat.getInstance().format(value));
576        }
577    
578    
579        /**
580         * Return decimal number formatted for default or given locale
581         * using given pattern.
582         */
583        public static String getDecimal(Number value, Locale locale, String pattern) {
584            NumberFormat formatter;
585            if (locale==null)
586                formatter = new java.text.DecimalFormat(pattern);
587            else {
588                formatter = NumberFormat.getNumberInstance(locale);
589                DecimalFormat df = (DecimalFormat) formatter;
590                df.applyPattern(pattern);
591                return df.format(value);
592            }
593            return (formatter.format(value));
594        }
595    
596    
597        /**
598         *  Return decimal for default locale using standard pattern.
599         */
600        public static String getDecimal(Number value) {
601            return getDecimal(value,(Locale) null,DECIMAL_PATTERN);
602        }
603    
604    
605    // ----------------------------------------------------------- Currency
606    
607    
608        /**
609         * Standard currency pattern.
610         * http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
611         */
612        public static String CURRENCY_PATTERN ="$" + DECIMAL_PATTERN;
613    
614    
615        /**
616         *  Return currency for default locale using standard pattern.
617         */
618        public static String getCurrency(Number value) {
619            return getDecimal(value,null,CURRENCY_PATTERN);
620        }
621    
622    
623    // --------------------------------------------------------------- Date
624    
625    
626        /**
627         * Default style for dates and times.
628         */
629        public static int DEFAULT = DateFormat.DEFAULT;
630    
631    
632        /**
633         * Short style for dates and times.
634         */
635        public static int SHORT = DateFormat.SHORT;
636    
637    
638        /**
639         * Medium style for dates and times.
640         */
641        public static int MEDIUM = DateFormat.MEDIUM;
642    
643    
644        /**
645         * Long style for dates and times.
646         */
647        public static int LONG = DateFormat.LONG;
648    
649    
650        /**
651         * Full style for dates and times.
652         */
653        public static int FULL = DateFormat.FULL;
654    
655    
656        /**
657         * Default lenient setting for getDate.
658         */
659        private static boolean LENIENT_DATE = false;
660    
661    
662        /**
663         * A "default" date format.
664         */
665        public static String ESCAPE_DATE_PATTERN = "yyyy-mm-dd";
666    
667    
668        /**
669         * Convert String to Date using given format.
670         * Returns null if conversion fails.
671         * Set lenient=false to disallow dates like 2001-9-32.
672         * http://java.sun.com/j2se/1.4/docs/api/java/text/SimpleDateFormat.html
673         * @author Hal Deadman
674         */
675        public static Date getDate(String dateDisplay,
676                String format, boolean lenient) {
677            if (dateDisplay == null) {
678                return null;
679            }
680            DateFormat df = null;
681            try {
682                if (format==null) {
683                    df = new SimpleDateFormat();
684                }
685                else {
686                    df = new SimpleDateFormat(format);
687                }
688                    // setLenient avoids allowing dates like 9/32/2001
689                    // which would otherwise parse to 10/2/2001
690                df.setLenient(false);
691                return df.parse(dateDisplay);
692            }
693            catch(ParseException e) {
694                return null;
695            }
696        }
697    
698    
699        /**
700         * Convert String to Date using given format.
701         * Returns null if conversion fails.
702         * Uses "strict" coNversion (lenient=false).
703         * @author Hal Deadman
704         */
705        public static Date getDate(String dateDisplay, String format) {
706            return getDate(dateDisplay,format,LENIENT_DATE);
707        }
708    
709    
710        /**
711         * Convert String to Date using a medium (weekday day month year) format.
712         * Returns null if conversion fails.
713         * Uses "strict" coNversion (lenient=false).
714         * @author Hal Deadman
715         */
716        public static Date getDate(String dateDisplay) {
717            return getDate(dateDisplay,null,LENIENT_DATE);
718        }
719    
720    
721        /**
722         * Return Date value using a String.
723         * Null or conversion error returns null.
724         * @param String representing Date
725         */
726        public static Date toDate(String string) {
727            if (string==null)
728                return null;
729            else try {
730                return getDate(string);
731            } catch (Throwable t) {
732                return null;
733            }
734        }
735    
736    
737        /**
738         * Convert date to String for given locale in given style.
739         * A null locale will return the default locale.
740         */
741        public static String getDate(Date date, Locale locale, int style) {
742            if (locale==null)
743                return (DateFormat.getDateInstance(style).format(date));
744            return (DateFormat.getDateInstance(style,locale).format(date));
745        }
746    
747    
748        /**
749         * Convert date to String for default locale in given style.
750         * A null locale will return the default locale.
751         */
752        public static String getDate(Date date, int style) {
753           return getDate(date,(Locale) null,style);
754        }
755    
756    
757        /**
758         * Convert date to String for default locale in DEFAULT style.
759         * A null locale will return the default locale.
760         */
761        public static String getDate(Date date) {
762           return getDate(date,(Locale) null,DEFAULT);
763        }
764    
765    
766        /**
767         * Return String value representing Date.
768         * Null returns null.
769         * @param Date
770         */
771        public static String toString(Date date) {
772            if (date==null)
773                return null;
774            else
775                return getDate(date);
776        }
777    
778    
779        /**
780         * Return String value representing Date.
781         * Null returns null.
782         * @param Date
783         */
784        public static String toEscape(Date date) {
785            if (date==null)
786                return null;
787            DateFormat df = null;
788            try {
789                df = new SimpleDateFormat(ESCAPE_DATE_PATTERN);
790            } catch (Throwable t) {
791                return null;
792            }
793            df.setLenient(false);
794            return df.format(date);
795        }
796    
797    
798    // ---------------------------------------------------------- Timestamp
799    
800        /**
801         * Date separator ["-"].
802         */
803        public static final String DATE_SEPARATOR = "-";
804    
805    
806        /**
807         * Time separator [":"].
808         */
809        public static final String TIME_SEPARATOR = ":";
810    
811    
812        /**
813         * Date Time separator [" "].
814         */
815        public static final String DATE_TIME_SEPARATOR = STRING_SPACE;
816    
817    
818        /**
819         * String to prepend to time [HH:MM:SS.d] 
820         * to create a Timestamp escape string ["0002-11-30"].
821         */
822        public static final String TIMESTAMP_DATE_ZERO = "0002-11-30";
823    
824    
825        /**
826         * String to append to date [YEAR-MM-DD] 
827         * to create a Timestamp escape string [" 00:00:00.0"].
828         * Note: includes leading space.
829         */
830        public static final String TIMESTAMP_TIME_ZERO = " 00:00:00.0";
831        
832    
833        /**
834         * Escape string representing
835         * "November 30, 0002 00:00:00".
836         */    
837         public static String ZERO_TIMESTAMP_DISPLAY = "2-11-30 00:00:00";
838    
839    
840        /**
841         * Timestamp representing ""November 30, 0002 00:00:00".
842         */
843        public static Timestamp ZERO_TIMESTAMP = new Timestamp((long) 00000000000000);
844    
845    
846    
847        /**
848         * Escape string to create Timestamp representing
849         * "January 1, 1970 00:00:00".
850         */
851        public static String NULL_TIMESTAMP_DISPLAY = "1970-01-01 00:00:00";
852    
853    
854        /**
855         * @deprecated Use NULL_TIMESTAMP_DISPLAY.
856         */
857        public static String NULL_TIMESTAMP_TEXT = "NULL_TIMESTAMP_DISPLAY";
858    
859    
860        /**
861         * Value needed to create Timestamp representing
862         * "January 1, 1970 00:00:00".
863         * From the documentation, you would think this would be
864         * Timestamp(0), but empirical tests show it to be
865         * Timestamp(18000000).
866         */
867        public static long NULL_TIME = (long) 18000000;
868    
869    
870        /**
871         * Timestamp representing "January 1, 1970 00:00:00".
872         */
873        public static Timestamp NULL_TIMESTAMP = new Timestamp(NULL_TIME);
874        
875        
876        
877        /**
878         * Timestamp representing "December 31, 2029, 23:59:59.9"
879         */
880        public static Timestamp MAX_TIMESTAMP = Timestamp.valueOf("2029-12-31 23:59:59.999");
881    
882    
883        /**
884         * Return the String representing "January 1, 1970 00:00:00".
885         */
886        public static String getTimestampDisplayNull() {
887            return NULL_TIMESTAMP_DISPLAY;
888        }
889    
890    
891        /**
892         * Return the String representing the current timestamp;
893         */
894        public static String getTimestampDisplay() {
895            return getTimestamp(new Timestamp(System.currentTimeMillis()));
896        }
897    
898    
899        /**
900         * @deprecated Use getTimestampDisplay.
901         */
902        public static String getTimestampText() {
903            return getTimestampDisplay();
904        }
905    
906    
907        /**
908         * Return null if timestamp is null or equals
909         * "January 1, 1970 00:00:00".
910         */
911        public static boolean isNull(Timestamp timestamp) {
912            return ((timestamp==null) || (timestamp.getTime()==NULL_TIME));
913        }
914    
915    
916        /**
917         * Factory method to return timestamp initialized to
918         * current system time.
919         * For timestamp as a String in the default format,
920         * use <code>getTimestamp().toString()</code>.
921         */
922        public static Timestamp getTimestamp() {
923            return new Timestamp(System.currentTimeMillis());
924        }
925    
926    
927        /**
928         * Convert timestamp to String for given locale in given style.
929         * A null locale will return the default locale.
930         */
931        public static String getTimestamp(Timestamp timestamp,
932                Locale locale, int style) {
933            Date date = (Date) timestamp;
934            if (locale==null)
935                return (DateFormat.getDateTimeInstance(style,style).
936                    format(date));
937            return (DateFormat.getDateTimeInstance(style,style,locale).
938                format(date));
939        }
940    
941    
942        /**
943         * Convert date to String for default locale in given style.
944         * A null locale will return the default locale.
945         */
946        public static String getTimestamp(Timestamp timestamp,
947                int style) {
948           return getTimestamp(timestamp,(Locale) null,style);
949        }
950    
951    
952        /**
953         * Convert date to String for default locale in DEFAULT style.
954         * A null locale will return the default locale.
955         */
956        public static String getTimestamp(Timestamp timestamp) {
957           return getTimestamp(timestamp,(Locale) null,DEFAULT);
958        }
959    
960    
961        /**
962         * Return Timestamp value using a String.
963         * Null or conversion error returns null.
964         * @param String representing Timestamp
965         */
966        public static Timestamp toTimestamp(String string) {
967            if (string==null)
968                return null;
969            else try {
970                return Timestamp.valueOf(string);
971            } catch (Throwable t) {
972                return null;
973            }
974        }
975    
976    
977        /**
978         * Return a Timestamp based on the parameters.
979         * Any nulls or conversion error returns null.
980         * @param year The year
981         * @param month The month
982         * @param day The day   
983         * @returns Timestamp for year-month-day
984         */    
985        public static Timestamp toTimestamp(String year, String month, String day) {
986            
987            if ((null==year) || (null==month) || (null==day)) return null;
988            
989            StringBuffer sb = new StringBuffer();
990            // YEAR-MM-DD 00:00:00.0
991            sb.append(year);   sb.append(DATE_SEPARATOR); 
992            sb.append(month);  sb.append(DATE_SEPARATOR); 
993            sb.append(day); 
994            
995            sb.append(TIMESTAMP_TIME_ZERO);
996            
997            return toTimestamp(sb.toString());        
998        }
999    
1000    
1001        /**
1002         * Return String value representing Timestamp.
1003         * Null returns null.
1004         * @param Timestamp
1005         */
1006        public static String toString(Timestamp timestamp) {
1007            if (timestamp==null)
1008                return null;
1009            else
1010                return timestamp.toString();
1011        }
1012    
1013    
1014    // ----------------------------------------------------------- Internet
1015    
1016    
1017        /**
1018         * Return the integer value of an IP address in dotted octet form, 
1019         * like that returned by request.getRemotehost).
1020         * :FIXME: Needs to be implemented; just returns zero.
1021         * @param Timestamp
1022         */
1023        public static Integer ipNode(String ipAddress) { 
1024            return INTEGER_ZERO;
1025        }
1026    
1027    
1028    }
1029