001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import java.net.MalformedURLException;
018    import java.net.URL;
019    
020    import java.util.regex.Matcher;
021    import java.util.regex.Pattern;
022    
023    /**
024     * Provides utility methods related to data validation and format checking.
025     *
026     * @author Brian Wing Shun Chan
027     * @author Alysa Carver
028     */
029    public class Validator {
030    
031            /**
032             * Returns <code>true</code> if the booleans are equal.
033             *
034             * @param  boolean1 the first boolean
035             * @param  boolean2 the second boolean
036             * @return <code>true</code> if the booleans are equal; <code>false</code>
037             *         otherwise
038             */
039            public static boolean equals(boolean boolean1, boolean boolean2) {
040                    if (boolean1 == boolean2) {
041                            return true;
042                    }
043                    else {
044                            return false;
045                    }
046            }
047    
048            /**
049             * Returns <code>true</code> if the bytes are equal.
050             *
051             * @param  byte1 the first byte
052             * @param  byte2 the second byte
053             * @return <code>true</code> if the bytes are equal; <code>false</code>
054             *         otherwise
055             */
056            public static boolean equals(byte byte1, byte byte2) {
057                    if (byte1 == byte2) {
058                            return true;
059                    }
060                    else {
061                            return false;
062                    }
063            }
064    
065            /**
066             * Returns <code>true</code> if the characters are equal.
067             *
068             * @param  char1 the first character
069             * @param  char2 the second character
070             * @return <code>true</code> if the characters are equal; <code>false</code>
071             *         otherwise
072             */
073            public static boolean equals(char char1, char char2) {
074                    if (char1 == char2) {
075                            return true;
076                    }
077                    else {
078                            return false;
079                    }
080            }
081    
082            /**
083             * Returns <code>true</code> if the doubles are equal.
084             *
085             * @param  double1 the first double
086             * @param  double2 the second double
087             * @return <code>true</code> if the doubles are equal; <code>false</code>
088             *         otherwise
089             */
090            public static boolean equals(double double1, double double2) {
091                    if (Double.compare(double1, double2) == 0) {
092                            return true;
093                    }
094                    else {
095                            return false;
096                    }
097            }
098    
099            /**
100             * Returns <code>true</code> if the floats are equal.
101             *
102             * @param  float1 the first float
103             * @param  float2 the second float
104             * @return <code>true</code> if the floats are equal; <code>false</code>
105             *         otherwise
106             */
107            public static boolean equals(float float1, float float2) {
108                    if (Float.compare(float1, float2) == 0) {
109                            return true;
110                    }
111                    else {
112                            return false;
113                    }
114            }
115    
116            /**
117             * Returns <code>true</code> if the integers are equal.
118             *
119             * @param  int1 the first integer
120             * @param  int2 the second integer
121             * @return <code>true</code> if the integers are equal; <code>false</code>
122             *         otherwise
123             */
124            public static boolean equals(int int1, int int2) {
125                    if (int1 == int2) {
126                            return true;
127                    }
128                    else {
129                            return false;
130                    }
131            }
132    
133            /**
134             * Returns <code>true</code> if the long integers are equal.
135             *
136             * @param  long1 the first long integer
137             * @param  long2 the second long integer
138             * @return <code>true</code> if the long integers are equal;
139             *         <code>false</code> otherwise
140             */
141            public static boolean equals(long long1, long long2) {
142                    if (long1 == long2) {
143                            return true;
144                    }
145                    else {
146                            return false;
147                    }
148            }
149    
150            /**
151             * Returns <code>true</code> if the objects are either equal, the same
152             * instance, or both <code>null</code>.
153             *
154             * @param  obj1 the first object
155             * @param  obj2 the second object
156             * @return <code>true</code> if the objects are either equal, the same
157             *         instance, or both <code>null</code>; <code>false</code> otherwise
158             */
159            public static boolean equals(Object obj1, Object obj2) {
160                    if ((obj1 == null) && (obj2 == null)) {
161                            return true;
162                    }
163                    else if ((obj1 == null) || (obj2 == null)) {
164                            return false;
165                    }
166                    else {
167                            return obj1.equals(obj2);
168                    }
169            }
170    
171            /**
172             * Returns <code>true</code> if the short integers are equal.
173             *
174             * @param  short1 the first short integer
175             * @param  short2 the second short integer
176             * @return <code>true</code> if the short integers are equal;
177             *         <code>false</code> otherwise
178             */
179            public static boolean equals(short short1, short short2) {
180                    if (short1 == short2) {
181                            return true;
182                    }
183                    else {
184                            return false;
185                    }
186            }
187    
188            /**
189             * Returns <code>true</code> if the string is an email address. The only
190             * requirements are that the string consist of two parts separated by an @
191             * symbol, and that it contain no whitespace.
192             *
193             * @param  address the string to check
194             * @return <code>true</code> if the string is an email address;
195             *         <code>false</code> otherwise
196             */
197            public static boolean isAddress(String address) {
198                    if (isNull(address)) {
199                            return false;
200                    }
201    
202                    String[] tokens = address.split(StringPool.AT);
203    
204                    if (tokens.length != 2) {
205                            return false;
206                    }
207    
208                    for (String token : tokens) {
209                            for (char c : token.toCharArray()) {
210                                    if (Character.isWhitespace(c)) {
211                                            return false;
212                                    }
213                            }
214                    }
215    
216                    return true;
217            }
218    
219            /**
220             * Returns <code>true</code> if the string is an alphanumeric name, meaning
221             * it contains nothing but English letters, numbers, and spaces.
222             *
223             * @param  name the string to check
224             * @return <code>true</code> if the string is an Alphanumeric name;
225             *         <code>false</code> otherwise
226             */
227            public static boolean isAlphanumericName(String name) {
228                    if (isNull(name)) {
229                            return false;
230                    }
231    
232                    for (char c : name.trim().toCharArray()) {
233                            if (!isChar(c) && !isDigit(c) && !Character.isWhitespace(c)) {
234                                    return false;
235                            }
236                    }
237    
238                    return true;
239            }
240    
241            /**
242             * Returns <code>true</code> if the character is in the ASCII character set.
243             * This includes characters with integer values between 32 and 126
244             * (inclusive).
245             *
246             * @param  c the character to check
247             * @return <code>true</code> if the character is in the ASCII character set;
248             *         <code>false</code> otherwise
249             */
250            public static boolean isAscii(char c) {
251                    int i = c;
252    
253                    if ((i >= 32) && (i <= 126)) {
254                            return true;
255                    }
256                    else {
257                            return false;
258                    }
259            }
260    
261            /**
262             * Returns <code>true</code> if the character is an upper or lower case
263             * English letter.
264             *
265             * @param  c the character to check
266             * @return <code>true</code> if the character is an upper or lower case
267             *         English letter; <code>false</code> otherwise
268             */
269            public static boolean isChar(char c) {
270                    int x = c;
271    
272                    if ((x >= _CHAR_BEGIN) && (x <= _CHAR_END)) {
273                            return true;
274                    }
275    
276                    return false;
277            }
278    
279            /**
280             * Returns <code>true</code> if string consists only of upper and lower case
281             * English letters.
282             *
283             * @param  s the string to check
284             * @return <code>true</code> if the string consists only of upper and lower
285             *         case English letters
286             */
287            public static boolean isChar(String s) {
288                    if (isNull(s)) {
289                            return false;
290                    }
291    
292                    for (char c : s.toCharArray()) {
293                            if (!isChar(c)) {
294                                    return false;
295                            }
296                    }
297    
298                    return true;
299            }
300    
301            /**
302             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
303             *
304             * @param  month the month to check
305             * @param  day the day to check
306             * @return <code>true</code> if the date is valid in the Gregorian calendar;
307             *         <code>false</code> otherwise
308             */
309            public static boolean isDate(int month, int day, int year) {
310                    return isGregorianDate(month, day, year);
311            }
312    
313            /**
314             * Returns <code>true</code> if the character is a digit between 0 and 9
315             * (inclusive).
316             *
317             * @param  c the character to check
318             * @return <code>true</code> if the character is a digit between 0 and 9
319             *         (inclusive); <code>false</code> otherwise
320             */
321            public static boolean isDigit(char c) {
322                    int x = c;
323    
324                    if ((x >= _DIGIT_BEGIN) && (x <= _DIGIT_END)) {
325                            return true;
326                    }
327    
328                    return false;
329            }
330    
331            /**
332             * Returns <code>true</code> if the string consists of only digits between 0
333             * and 9 (inclusive).
334             *
335             * @param  s the string to check
336             * @return <code>true</code> if the string consists of only digits between 0
337             *         and 9 (inclusive); <code>false</code> otherwise
338             */
339            public static boolean isDigit(String s) {
340                    if (isNull(s)) {
341                            return false;
342                    }
343    
344                    for (char c : s.toCharArray()) {
345                            if (!isDigit(c)) {
346                                    return false;
347                            }
348                    }
349    
350                    return true;
351            }
352    
353            /**
354             * Returns <code>true</code> if the string is a valid domain name. See
355             * RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952 (section B.
356             * Lexical grammar).
357             *
358             * @param  domainName the string to check
359             * @return <code>true</code> if the string is a valid domain name;
360             *         <code>false</code> otherwise
361             */
362            public static boolean isDomain(String domainName) {
363    
364                    // See RFC-1034 (section 3), RFC-1123 (section 2.1), and RFC-952
365                    // (section B. Lexical grammar)
366    
367                    if (isNull(domainName)) {
368                            return false;
369                    }
370    
371                    if (domainName.length() > 255) {
372                            return false;
373                    }
374    
375                    String[] domainNameArray = StringUtil.split(
376                            domainName, CharPool.PERIOD);
377    
378                    for (String domainNamePart : domainNameArray) {
379                            char[] domainNamePartCharArray = domainNamePart.toCharArray();
380    
381                            for (int i = 0; i < domainNamePartCharArray.length; i++) {
382                                    char c = domainNamePartCharArray[i];
383    
384                                    if ((i == 0) && (c == CharPool.DASH)) {
385                                            return false;
386                                    }
387                                    else if ((i == (domainNamePartCharArray.length - 1)) &&
388                                                     (c == CharPool.DASH)) {
389    
390                                            return false;
391                                    }
392                                    else if ((!isChar(c)) && (!isDigit(c)) &&
393                                                     (c != CharPool.DASH)) {
394    
395                                            return false;
396                                    }
397                            }
398                    }
399    
400                    return true;
401            }
402    
403            /**
404             * Returns <code>true</code> if the string is a valid email address.
405             *
406             * @param  emailAddress the string to check
407             * @return <code>true</code> if the string is a valid email address;
408             *         <code>false</code> otherwise
409             */
410            public static boolean isEmailAddress(String emailAddress) {
411                    Matcher matcher = _emailAddressPattern.matcher(emailAddress);
412    
413                    return matcher.matches();
414            }
415    
416            /**
417             * Returns <code>true</code> if the character is a special character in an
418             * email address.
419             *
420             * @param  c the character to check
421             * @return <code>true</code> if the character is a special character in an
422             *         email address; <code>false</code> otherwise
423             */
424            public static boolean isEmailAddressSpecialChar(char c) {
425    
426                    // LEP-1445
427    
428                    for (int i = 0; i < _EMAIL_ADDRESS_SPECIAL_CHAR.length; i++) {
429                            if (c == _EMAIL_ADDRESS_SPECIAL_CHAR[i]) {
430                                    return true;
431                            }
432                    }
433    
434                    return false;
435            }
436    
437            /**
438             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
439             *
440             * @param  month the month (0-based, meaning 0 for January)
441             * @param  day the day of the month
442             * @param  year the year
443             * @return <code>true</code> if the date is valid; <code>false</code>
444             *         otherwise
445             */
446            public static boolean isGregorianDate(int month, int day, int year) {
447                    if ((month < 0) || (month > 11)) {
448                            return false;
449                    }
450    
451                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
452    
453                    if (month == 1) {
454                            int febMax = 28;
455    
456                            if (((year % 4) == 0) && ((year % 100) != 0) ||
457                                    ((year % 400) == 0)) {
458    
459                                    febMax = 29;
460                            }
461    
462                            if ((day < 1) || (day > febMax)) {
463                                    return false;
464                            }
465                    }
466                    else if ((day < 1) || (day > months[month])) {
467                            return false;
468                    }
469    
470                    return true;
471            }
472    
473            /**
474             * Returns <code>true</code> if the string is a hexidecimal number. At
475             * present the only requirement is that the string is not <code>null</code>;
476             * it does not actually check the format of the string.
477             *
478             * @param  s the string to check
479             * @return <code>true</code> if the string is a hexidecimal number;
480             *         <code>false</code> otherwise
481             * @see    #isNull(String)
482             */
483            public static boolean isHex(String s) {
484                    if (isNull(s)) {
485                            return false;
486                    }
487    
488                    return true;
489            }
490    
491            /**
492             * Returns <code>true</code> if the string is an HTML document. The only
493             * requirement is that it contain the opening and closing html tags.
494             *
495             * @param  s the string to check
496             * @return <code>true</code> if the string is an HTML document;
497             *         <code>false</code> otherwise
498             */
499            public static boolean isHTML(String s) {
500                    if (isNull(s)) {
501                            return false;
502                    }
503    
504                    if (((s.indexOf("<html>") != -1) || (s.indexOf("<HTML>") != -1)) &&
505                            ((s.indexOf("</html>") != -1) || (s.indexOf("</HTML>") != -1))) {
506    
507                            return true;
508                    }
509    
510                    return false;
511            }
512    
513            /**
514             * Returns <code>true</code> if the string is a valid IPv4 IP address.
515             *
516             * @param  ipAddress the string to check
517             * @return <code>true</code> if the string is an IPv4 IP address;
518             *         <code>false</code> otherwise
519             */
520            public static boolean isIPAddress(String ipAddress) {
521                    Matcher matcher = _ipAddressPattern.matcher(ipAddress);
522    
523                    return matcher.matches();
524            }
525    
526            /**
527             * Returns <code>true</code> if the date is valid in the Julian calendar.
528             *
529             * @param  month the month (0-based, meaning 0 for January)
530             * @param  day the day of the month
531             * @param  year the year
532             * @return <code>true</code> if the date is valid; <code>false</code>
533             *         otherwise
534             */
535            public static boolean isJulianDate(int month, int day, int year) {
536                    if ((month < 0) || (month > 11)) {
537                            return false;
538                    }
539    
540                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
541    
542                    if (month == 1) {
543                            int febMax = 28;
544    
545                            if ((year % 4) == 0) {
546                                    febMax = 29;
547                            }
548    
549                            if ((day < 1) || (day > febMax)) {
550                                    return false;
551                            }
552                    }
553                    else if ((day < 1) || (day > months[month])) {
554                            return false;
555                    }
556    
557                    return true;
558            }
559    
560            /**
561             * Returns <code>true</code> if the string contains a valid number according
562             * to the Luhn algorithm, commonly used to validate credit card numbers.
563             *
564             * @param  number the string to check
565             * @return <code>true</code> if the string contains a valid number according
566             *         to the Luhn algorithm; <code>false</code> otherwise
567             */
568            public static boolean isLUHN(String number) {
569                    if (number == null) {
570                            return false;
571                    }
572    
573                    number = StringUtil.reverse(number);
574    
575                    int total = 0;
576    
577                    for (int i = 0; i < number.length(); i++) {
578                            int x = 0;
579    
580                            if (((i + 1) % 2) == 0) {
581                                    x = Integer.parseInt(number.substring(i, i + 1)) * 2;
582    
583                                    if (x >= 10) {
584                                            String s = String.valueOf(x);
585    
586                                            x = Integer.parseInt(s.substring(0, 1)) +
587                                                    Integer.parseInt(s.substring(1, 2));
588                                    }
589                            }
590                            else {
591                                    x = Integer.parseInt(number.substring(i, i + 1));
592                            }
593    
594                            total = total + x;
595                    }
596    
597                    if ((total % 10) == 0) {
598                            return true;
599                    }
600                    else {
601                            return false;
602                    }
603            }
604    
605            /**
606             * Returns <code>true</code> if the string is a name, meaning it contains
607             * nothing but English letters and spaces.
608             *
609             * @param  name the string to check
610             * @return <code>true</code> if the string is a name; <code>false</code>
611             *         otherwise
612             */
613            public static boolean isName(String name) {
614                    if (isNull(name)) {
615                            return false;
616                    }
617    
618                    for (char c : name.trim().toCharArray()) {
619                            if (!isChar(c) && !Character.isWhitespace(c)) {
620                                    return false;
621                            }
622                    }
623    
624                    return true;
625            }
626    
627            /**
628             * Returns <code>true</code> if the long number object is not
629             * <code>null</code>, meaning it is neither a <code>null</code> reference or
630             * zero.
631             *
632             * @param  l the long number object to check
633             * @return <code>true</code> if the long number object is not
634             *         <code>null</code>; <code>false</code> otherwise
635             */
636            public static boolean isNotNull(Long l) {
637                    return !isNull(l);
638            }
639    
640            /**
641             * Returns <code>true</code> if the object is not <code>null</code>, using
642             * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if
643             * the object is one of these types.
644             *
645             * @param  obj the object to check
646             * @return <code>true</code> if the object is not <code>null</code>;
647             *         <code>false</code> otherwise
648             */
649            public static boolean isNotNull(Object obj) {
650                    return !isNull(obj);
651            }
652    
653            /**
654             * Returns <code>true</code> if the array is not <code>null</code>, meaning
655             * it is neither a <code>null</code> reference or empty.
656             *
657             * @param  array the array to check
658             * @return <code>true</code> if the array is not <code>null</code>;
659             *         <code>false</code> otherwise
660             */
661            public static boolean isNotNull(Object[] array) {
662                    return !isNull(array);
663            }
664    
665            /**
666             * Returns <code>true</code> if the string is not <code>null</code>, meaning
667             * it is not a <code>null</code> reference, nothing but spaces, or the
668             * string "<code>null</code>".
669             *
670             * @param  s the string to check
671             * @return <code>true</code> if the string is not <code>null</code>;
672             *         <code>false</code> otherwise
673             */
674            public static boolean isNotNull(String s) {
675                    return !isNull(s);
676            }
677    
678            /**
679             * Returns <code>true</code> if the long number object is <code>null</code>,
680             * meaning it is either a <code>null</code> reference or zero.
681             *
682             * @param  l the long number object to check
683             * @return <code>true</code> if the long number object is <code>null</code>;
684             *         <code>false</code> otherwise
685             */
686            public static boolean isNull(Long l) {
687                    if ((l == null) || (l.longValue() == 0)) {
688                            return true;
689                    }
690                    else {
691                            return false;
692                    }
693            }
694    
695            /**
696             * Returns <code>true</code> if the object is <code>null</code>, using the
697             * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object
698             * is one of these types.
699             *
700             * @param  obj the object to check
701             * @return <code>true</code> if the object is <code>null</code>;
702             *         <code>false</code> otherwise
703             */
704            public static boolean isNull(Object obj) {
705                    if (obj instanceof Long) {
706                            return isNull((Long)obj);
707                    }
708                    else if (obj instanceof String) {
709                            return isNull((String)obj);
710                    }
711                    else if (obj == null) {
712                            return true;
713                    }
714                    else {
715                            return false;
716                    }
717            }
718    
719            /**
720             * Returns <code>true</code> if the array is <code>null</code>, meaning it
721             * is either a <code>null</code> reference or empty.
722             *
723             * @param  array the array to check
724             * @return <code>true</code> if the array is <code>null</code>;
725             *         <code>false</code> otherwise
726             */
727            public static boolean isNull(Object[] array) {
728                    if ((array == null) || (array.length == 0)) {
729                            return true;
730                    }
731                    else {
732                            return false;
733                    }
734            }
735    
736            /**
737             * Returns <code>true</code> if the string is <code>null</code>, meaning it
738             * is a <code>null</code> reference, nothing but spaces, or the string
739             * "<code>null</code>".
740             *
741             * @param  s the string to check
742             * @return <code>true</code> if the string is <code>null</code>;
743             *         <code>false</code> otherwise
744             */
745            public static boolean isNull(String s) {
746                    if (s == null) {
747                            return true;
748                    }
749    
750                    int counter = 0;
751    
752                    for (int i = 0; i < s.length(); i++) {
753                            char c = s.charAt(i);
754    
755                            if (c == CharPool.SPACE) {
756                                    continue;
757                            }
758                            else if (counter > 3) {
759                                    return false;
760                            }
761    
762                            if (counter == 0) {
763                                    if (c != CharPool.LOWER_CASE_N) {
764                                            return false;
765                                    }
766                            }
767                            else if (counter == 1) {
768                                    if (c != CharPool.LOWER_CASE_U) {
769                                            return false;
770                                    }
771                            }
772                            else if ((counter == 2) || (counter == 3)) {
773                                    if (c != CharPool.LOWER_CASE_L) {
774                                            return false;
775                                    }
776                            }
777    
778                            counter++;
779                    }
780    
781                    if ((counter == 0) || (counter == 4)) {
782                            return true;
783                    }
784    
785                    return false;
786            }
787    
788            /**
789             * Returns <code>true</code> if the string is a decimal integer number,
790             * meaning it contains nothing but decimal digits.
791             *
792             * @param  number the string to check
793             * @return <code>true</code> if the string is a decimal integer number;
794             *         <code>false</code> otherwise
795             */
796            public static boolean isNumber(String number) {
797                    if (isNull(number)) {
798                            return false;
799                    }
800    
801                    for (char c : number.toCharArray()) {
802                            if (!isDigit(c)) {
803                                    return false;
804                            }
805                    }
806    
807                    return true;
808            }
809    
810            /**
811             * Returns <code>true</code> if the string is a valid password, meaning it
812             * is at least four characters long and contains only letters and decimal
813             * digits.
814             *
815             * @return <code>true</code> if the string is a valid password;
816             *         <code>false</code> otherwise
817             */
818            public static boolean isPassword(String password) {
819                    if (isNull(password)) {
820                            return false;
821                    }
822    
823                    if (password.length() < 4) {
824                            return false;
825                    }
826    
827                    for (char c : password.toCharArray()) {
828                            if (!isChar(c) && !isDigit(c)) {
829                                    return false;
830                            }
831                    }
832    
833                    return true;
834            }
835    
836            /**
837             * Returns <code>true</code> if the string is a valid phone number. The only
838             * requirement is that there are decimal digits in the string; length and
839             * format are not checked.
840             *
841             * @param  phoneNumber the string to check
842             * @return <code>true</code> if the string is a valid phone number;
843             *         <code>false</code> otherwise
844             */
845            public static boolean isPhoneNumber(String phoneNumber) {
846                    return isNumber(StringUtil.extractDigits(phoneNumber));
847            }
848    
849            /**
850             * Returns <code>true</code> if the string is a valid URL based on the rules
851             * in {@link java.net.URL}.
852             *
853             * @param  url the string to check
854             * @return <code>true</code> if the string is a valid URL;
855             *         <code>false</code> otherwise
856             */
857            public static boolean isUrl(String url) {
858                    if (Validator.isNotNull(url)) {
859                            if (url.indexOf(CharPool.COLON) == -1) {
860                                    return false;
861                            }
862    
863                            try {
864                                    new URL(url);
865    
866                                    return true;
867                            }
868                            catch (MalformedURLException murle) {
869                            }
870                    }
871    
872                    return false;
873            }
874    
875            /**
876             * Returns <code>true</code> if the string is a valid variable name in Java.
877             *
878             * @param  variableName the string to check
879             * @return <code>true</code> if the string is a valid variable name in Java;
880             *         <code>false</code> otherwise
881             */
882            public static boolean isVariableName(String variableName) {
883                    if (isNull(variableName)) {
884                            return false;
885                    }
886    
887                    Matcher matcher = _variableNamePattern.matcher(variableName);
888    
889                    if (matcher.matches()) {
890                            return true;
891                    }
892                    else {
893                            return false;
894                    }
895            }
896    
897            /**
898             * Returns <code>true</code> if the string is a valid variable term, meaning
899             * it begins with "[$" and ends with "$]".
900             *
901             * @param  s the string to check
902             * @return <code>true</code> if the string is a valid variable term;
903             *         <code>false</code> otherwise
904             */
905            public static boolean isVariableTerm(String s) {
906                    if (s.startsWith(_VARIABLE_TERM_BEGIN) &&
907                            s.endsWith(_VARIABLE_TERM_END)) {
908    
909                            return true;
910                    }
911                    else {
912                            return false;
913                    }
914            }
915    
916            /**
917             * Returns <code>true</code> if the character is whitespace, meaning it is
918             * either the <code>null</code> character '0' or whitespace according to
919             * {@link java.lang.Character#isWhitespace(char)}.
920             *
921             * @param  c the character to check
922             * @return <code>true</code> if the character is whitespace;
923             *         <code>false</code> otherwise
924             */
925            public static boolean isWhitespace(char c) {
926                    int i = c;
927    
928                    if ((i == 0) || Character.isWhitespace(c)) {
929                            return true;
930                    }
931                    else {
932                            return false;
933                    }
934            }
935    
936            /**
937             * Returns <code>true</code> if the string is an XML document. The only
938             * requirement is that it contain either the xml start tag "<?xml" or the
939             * empty document tag "<root />".
940             *
941             * @param  s the string to check
942             * @return <code>true</code> if the string is an XML document;
943             *         <code>false</code> otherwise
944             */
945            public static boolean isXml(String s) {
946                    if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) {
947                            return true;
948                    }
949                    else {
950                            return false;
951                    }
952            }
953    
954            private static final int _CHAR_BEGIN = 65;
955    
956            private static final int _CHAR_END = 122;
957    
958            private static final int _DIGIT_BEGIN = 48;
959    
960            private static final int _DIGIT_END = 57;
961    
962            private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] {
963                    '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^',
964                    '_', '`', '{', '|', '}', '~'
965            };
966    
967            private static final String _VARIABLE_TERM_BEGIN = "[$";
968    
969            private static final String _VARIABLE_TERM_END = "$]";
970    
971            private static final String _XML_BEGIN = "<?xml";
972    
973            private static final String _XML_EMPTY = "<root />";
974    
975            private static Pattern _emailAddressPattern = Pattern.compile(
976                    "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" +
977                    "(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?");
978            private static Pattern _ipAddressPattern = Pattern.compile(
979                    "\\b" +
980                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
981                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
982                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
983                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])" +
984                    "\\b");
985            private static Pattern _variableNamePattern = Pattern.compile(
986                    "[_a-zA-Z]+[_a-zA-Z0-9]*");
987    
988    }