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                    if (domainName.startsWith(StringPool.PERIOD) ||
376                            domainName.endsWith(StringPool.PERIOD)) {
377    
378                            return false;
379                    }
380    
381                    if (!domainName.contains(StringPool.PERIOD) &&
382                            !domainName.equals(_LOCALHOST)) {
383    
384                            return false;
385                    }
386    
387                    String[] domainNameArray = StringUtil.split(
388                            domainName, CharPool.PERIOD);
389    
390                    for (String domainNamePart : domainNameArray) {
391                            char[] domainNamePartCharArray = domainNamePart.toCharArray();
392    
393                            for (int i = 0; i < domainNamePartCharArray.length; i++) {
394                                    char c = domainNamePartCharArray[i];
395    
396                                    if ((i == 0) && (c == CharPool.DASH)) {
397                                            return false;
398                                    }
399    
400                                    if ((i == (domainNamePartCharArray.length - 1)) &&
401                                            (c == CharPool.DASH)) {
402    
403                                            return false;
404                                    }
405    
406                                    if ((!isChar(c)) && (!isDigit(c)) && (c != CharPool.DASH)) {
407                                            return false;
408                                    }
409                            }
410                    }
411    
412                    return true;
413            }
414    
415            /**
416             * Returns <code>true</code> if the string is a valid email address.
417             *
418             * @param  emailAddress the string to check
419             * @return <code>true</code> if the string is a valid email address;
420             *         <code>false</code> otherwise
421             */
422            public static boolean isEmailAddress(String emailAddress) {
423                    Matcher matcher = _emailAddressPattern.matcher(emailAddress);
424    
425                    return matcher.matches();
426            }
427    
428            /**
429             * Returns <code>true</code> if the character is a special character in an
430             * email address.
431             *
432             * @param  c the character to check
433             * @return <code>true</code> if the character is a special character in an
434             *         email address; <code>false</code> otherwise
435             */
436            public static boolean isEmailAddressSpecialChar(char c) {
437    
438                    // LEP-1445
439    
440                    for (int i = 0; i < _EMAIL_ADDRESS_SPECIAL_CHAR.length; i++) {
441                            if (c == _EMAIL_ADDRESS_SPECIAL_CHAR[i]) {
442                                    return true;
443                            }
444                    }
445    
446                    return false;
447            }
448    
449            /**
450             * Returns <code>true</code> if the date is valid in the Gregorian calendar.
451             *
452             * @param  month the month (0-based, meaning 0 for January)
453             * @param  day the day of the month
454             * @param  year the year
455             * @return <code>true</code> if the date is valid; <code>false</code>
456             *         otherwise
457             */
458            public static boolean isGregorianDate(int month, int day, int year) {
459                    if ((month < 0) || (month > 11)) {
460                            return false;
461                    }
462    
463                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
464    
465                    if (month == 1) {
466                            int febMax = 28;
467    
468                            if (((year % 4) == 0) && ((year % 100) != 0) ||
469                                    ((year % 400) == 0)) {
470    
471                                    febMax = 29;
472                            }
473    
474                            if ((day < 1) || (day > febMax)) {
475                                    return false;
476                            }
477                    }
478                    else if ((day < 1) || (day > months[month])) {
479                            return false;
480                    }
481    
482                    return true;
483            }
484    
485            /**
486             * Returns <code>true</code> if the string is a hexidecimal number. At
487             * present the only requirement is that the string is not <code>null</code>;
488             * it does not actually check the format of the string.
489             *
490             * @param  s the string to check
491             * @return <code>true</code> if the string is a hexidecimal number;
492             *         <code>false</code> otherwise
493             * @see    #isNull(String)
494             */
495            public static boolean isHex(String s) {
496                    if (isNull(s)) {
497                            return false;
498                    }
499    
500                    return true;
501            }
502    
503            /**
504             * Returns <code>true</code> if the string is an HTML document. The only
505             * requirement is that it contain the opening and closing html tags.
506             *
507             * @param  s the string to check
508             * @return <code>true</code> if the string is an HTML document;
509             *         <code>false</code> otherwise
510             */
511            public static boolean isHTML(String s) {
512                    if (isNull(s)) {
513                            return false;
514                    }
515    
516                    if (((s.indexOf("<html>") != -1) || (s.indexOf("<HTML>") != -1)) &&
517                            ((s.indexOf("</html>") != -1) || (s.indexOf("</HTML>") != -1))) {
518    
519                            return true;
520                    }
521    
522                    return false;
523            }
524    
525            /**
526             * Returns <code>true</code> if the string is a valid IPv4 IP address.
527             *
528             * @param  ipAddress the string to check
529             * @return <code>true</code> if the string is an IPv4 IP address;
530             *         <code>false</code> otherwise
531             */
532            public static boolean isIPAddress(String ipAddress) {
533                    Matcher matcher = _ipAddressPattern.matcher(ipAddress);
534    
535                    return matcher.matches();
536            }
537    
538            /**
539             * Returns <code>true</code> if the date is valid in the Julian calendar.
540             *
541             * @param  month the month (0-based, meaning 0 for January)
542             * @param  day the day of the month
543             * @param  year the year
544             * @return <code>true</code> if the date is valid; <code>false</code>
545             *         otherwise
546             */
547            public static boolean isJulianDate(int month, int day, int year) {
548                    if ((month < 0) || (month > 11)) {
549                            return false;
550                    }
551    
552                    int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
553    
554                    if (month == 1) {
555                            int febMax = 28;
556    
557                            if ((year % 4) == 0) {
558                                    febMax = 29;
559                            }
560    
561                            if ((day < 1) || (day > febMax)) {
562                                    return false;
563                            }
564                    }
565                    else if ((day < 1) || (day > months[month])) {
566                            return false;
567                    }
568    
569                    return true;
570            }
571    
572            /**
573             * Returns <code>true</code> if the string contains a valid number according
574             * to the Luhn algorithm, commonly used to validate credit card numbers.
575             *
576             * @param  number the string to check
577             * @return <code>true</code> if the string contains a valid number according
578             *         to the Luhn algorithm; <code>false</code> otherwise
579             */
580            public static boolean isLUHN(String number) {
581                    if (number == null) {
582                            return false;
583                    }
584    
585                    number = StringUtil.reverse(number);
586    
587                    int total = 0;
588    
589                    for (int i = 0; i < number.length(); i++) {
590                            int x = 0;
591    
592                            if (((i + 1) % 2) == 0) {
593                                    x = Integer.parseInt(number.substring(i, i + 1)) * 2;
594    
595                                    if (x >= 10) {
596                                            String s = String.valueOf(x);
597    
598                                            x = Integer.parseInt(s.substring(0, 1)) +
599                                                    Integer.parseInt(s.substring(1, 2));
600                                    }
601                            }
602                            else {
603                                    x = Integer.parseInt(number.substring(i, i + 1));
604                            }
605    
606                            total = total + x;
607                    }
608    
609                    if ((total % 10) == 0) {
610                            return true;
611                    }
612                    else {
613                            return false;
614                    }
615            }
616    
617            /**
618             * Returns <code>true</code> if the string is a name, meaning it contains
619             * nothing but English letters and spaces.
620             *
621             * @param  name the string to check
622             * @return <code>true</code> if the string is a name; <code>false</code>
623             *         otherwise
624             */
625            public static boolean isName(String name) {
626                    if (isNull(name)) {
627                            return false;
628                    }
629    
630                    for (char c : name.trim().toCharArray()) {
631                            if (!isChar(c) && !Character.isWhitespace(c)) {
632                                    return false;
633                            }
634                    }
635    
636                    return true;
637            }
638    
639            /**
640             * Returns <code>true</code> if the long number object is not
641             * <code>null</code>, meaning it is neither a <code>null</code> reference or
642             * zero.
643             *
644             * @param  l the long number object to check
645             * @return <code>true</code> if the long number object is not
646             *         <code>null</code>; <code>false</code> otherwise
647             */
648            public static boolean isNotNull(Long l) {
649                    return !isNull(l);
650            }
651    
652            /**
653             * Returns <code>true</code> if the object is not <code>null</code>, using
654             * the rules from {@link #isNotNull(Long)} or {@link #isNotNull(String)} if
655             * the object is one of these types.
656             *
657             * @param  obj the object to check
658             * @return <code>true</code> if the object is not <code>null</code>;
659             *         <code>false</code> otherwise
660             */
661            public static boolean isNotNull(Object obj) {
662                    return !isNull(obj);
663            }
664    
665            /**
666             * Returns <code>true</code> if the array is not <code>null</code>, meaning
667             * it is neither a <code>null</code> reference or empty.
668             *
669             * @param  array the array to check
670             * @return <code>true</code> if the array is not <code>null</code>;
671             *         <code>false</code> otherwise
672             */
673            public static boolean isNotNull(Object[] array) {
674                    return !isNull(array);
675            }
676    
677            /**
678             * Returns <code>true</code> if the string is not <code>null</code>, meaning
679             * it is not a <code>null</code> reference, nothing but spaces, or the
680             * string "<code>null</code>".
681             *
682             * @param  s the string to check
683             * @return <code>true</code> if the string is not <code>null</code>;
684             *         <code>false</code> otherwise
685             */
686            public static boolean isNotNull(String s) {
687                    return !isNull(s);
688            }
689    
690            /**
691             * Returns <code>true</code> if the long number object is <code>null</code>,
692             * meaning it is either a <code>null</code> reference or zero.
693             *
694             * @param  l the long number object to check
695             * @return <code>true</code> if the long number object is <code>null</code>;
696             *         <code>false</code> otherwise
697             */
698            public static boolean isNull(Long l) {
699                    if ((l == null) || (l.longValue() == 0)) {
700                            return true;
701                    }
702                    else {
703                            return false;
704                    }
705            }
706    
707            /**
708             * Returns <code>true</code> if the object is <code>null</code>, using the
709             * rules from {@link #isNull(Long)} or {@link #isNull(String)} if the object
710             * is one of these types.
711             *
712             * @param  obj the object to check
713             * @return <code>true</code> if the object is <code>null</code>;
714             *         <code>false</code> otherwise
715             */
716            public static boolean isNull(Object obj) {
717                    if (obj instanceof Long) {
718                            return isNull((Long)obj);
719                    }
720                    else if (obj instanceof String) {
721                            return isNull((String)obj);
722                    }
723                    else if (obj == null) {
724                            return true;
725                    }
726                    else {
727                            return false;
728                    }
729            }
730    
731            /**
732             * Returns <code>true</code> if the array is <code>null</code>, meaning it
733             * is either a <code>null</code> reference or empty.
734             *
735             * @param  array the array to check
736             * @return <code>true</code> if the array is <code>null</code>;
737             *         <code>false</code> otherwise
738             */
739            public static boolean isNull(Object[] array) {
740                    if ((array == null) || (array.length == 0)) {
741                            return true;
742                    }
743                    else {
744                            return false;
745                    }
746            }
747    
748            /**
749             * Returns <code>true</code> if the string is <code>null</code>, meaning it
750             * is a <code>null</code> reference, nothing but spaces, or the string
751             * "<code>null</code>".
752             *
753             * @param  s the string to check
754             * @return <code>true</code> if the string is <code>null</code>;
755             *         <code>false</code> otherwise
756             */
757            public static boolean isNull(String s) {
758                    if (s == null) {
759                            return true;
760                    }
761    
762                    int counter = 0;
763    
764                    for (int i = 0; i < s.length(); i++) {
765                            char c = s.charAt(i);
766    
767                            if (c == CharPool.SPACE) {
768                                    continue;
769                            }
770                            else if (counter > 3) {
771                                    return false;
772                            }
773    
774                            if (counter == 0) {
775                                    if (c != CharPool.LOWER_CASE_N) {
776                                            return false;
777                                    }
778                            }
779                            else if (counter == 1) {
780                                    if (c != CharPool.LOWER_CASE_U) {
781                                            return false;
782                                    }
783                            }
784                            else if ((counter == 2) || (counter == 3)) {
785                                    if (c != CharPool.LOWER_CASE_L) {
786                                            return false;
787                                    }
788                            }
789    
790                            counter++;
791                    }
792    
793                    if ((counter == 0) || (counter == 4)) {
794                            return true;
795                    }
796    
797                    return false;
798            }
799    
800            /**
801             * Returns <code>true</code> if the string is a decimal integer number,
802             * meaning it contains nothing but decimal digits.
803             *
804             * @param  number the string to check
805             * @return <code>true</code> if the string is a decimal integer number;
806             *         <code>false</code> otherwise
807             */
808            public static boolean isNumber(String number) {
809                    if (isNull(number)) {
810                            return false;
811                    }
812    
813                    for (char c : number.toCharArray()) {
814                            if (!isDigit(c)) {
815                                    return false;
816                            }
817                    }
818    
819                    return true;
820            }
821    
822            /**
823             * Returns <code>true</code> if the string is a valid password, meaning it
824             * is at least four characters long and contains only letters and decimal
825             * digits.
826             *
827             * @return <code>true</code> if the string is a valid password;
828             *         <code>false</code> otherwise
829             */
830            public static boolean isPassword(String password) {
831                    if (isNull(password)) {
832                            return false;
833                    }
834    
835                    if (password.length() < 4) {
836                            return false;
837                    }
838    
839                    for (char c : password.toCharArray()) {
840                            if (!isChar(c) && !isDigit(c)) {
841                                    return false;
842                            }
843                    }
844    
845                    return true;
846            }
847    
848            /**
849             * Returns <code>true</code> if the string is a valid phone number. The only
850             * requirement is that there are decimal digits in the string; length and
851             * format are not checked.
852             *
853             * @param  phoneNumber the string to check
854             * @return <code>true</code> if the string is a valid phone number;
855             *         <code>false</code> otherwise
856             */
857            public static boolean isPhoneNumber(String phoneNumber) {
858                    return isNumber(StringUtil.extractDigits(phoneNumber));
859            }
860    
861            /**
862             * Returns <code>true</code> if the string is a valid URL based on the rules
863             * in {@link java.net.URL}.
864             *
865             * @param  url the string to check
866             * @return <code>true</code> if the string is a valid URL;
867             *         <code>false</code> otherwise
868             */
869            public static boolean isUrl(String url) {
870                    if (Validator.isNotNull(url)) {
871                            if (url.indexOf(CharPool.COLON) == -1) {
872                                    return false;
873                            }
874    
875                            try {
876                                    new URL(url);
877    
878                                    return true;
879                            }
880                            catch (MalformedURLException murle) {
881                            }
882                    }
883    
884                    return false;
885            }
886    
887            /**
888             * Returns <code>true</code> if the string is a valid variable name in Java.
889             *
890             * @param  variableName the string to check
891             * @return <code>true</code> if the string is a valid variable name in Java;
892             *         <code>false</code> otherwise
893             */
894            public static boolean isVariableName(String variableName) {
895                    if (isNull(variableName)) {
896                            return false;
897                    }
898    
899                    Matcher matcher = _variableNamePattern.matcher(variableName);
900    
901                    if (matcher.matches()) {
902                            return true;
903                    }
904                    else {
905                            return false;
906                    }
907            }
908    
909            /**
910             * Returns <code>true</code> if the string is a valid variable term, meaning
911             * it begins with "[$" and ends with "$]".
912             *
913             * @param  s the string to check
914             * @return <code>true</code> if the string is a valid variable term;
915             *         <code>false</code> otherwise
916             */
917            public static boolean isVariableTerm(String s) {
918                    if (s.startsWith(_VARIABLE_TERM_BEGIN) &&
919                            s.endsWith(_VARIABLE_TERM_END)) {
920    
921                            return true;
922                    }
923                    else {
924                            return false;
925                    }
926            }
927    
928            /**
929             * Returns <code>true</code> if the character is whitespace, meaning it is
930             * either the <code>null</code> character '0' or whitespace according to
931             * {@link java.lang.Character#isWhitespace(char)}.
932             *
933             * @param  c the character to check
934             * @return <code>true</code> if the character is whitespace;
935             *         <code>false</code> otherwise
936             */
937            public static boolean isWhitespace(char c) {
938                    int i = c;
939    
940                    if ((i == 0) || Character.isWhitespace(c)) {
941                            return true;
942                    }
943                    else {
944                            return false;
945                    }
946            }
947    
948            /**
949             * Returns <code>true</code> if the string is an XML document. The only
950             * requirement is that it contain either the xml start tag "<?xml" or the
951             * empty document tag "<root />".
952             *
953             * @param  s the string to check
954             * @return <code>true</code> if the string is an XML document;
955             *         <code>false</code> otherwise
956             */
957            public static boolean isXml(String s) {
958                    if (s.startsWith(_XML_BEGIN) || s.startsWith(_XML_EMPTY)) {
959                            return true;
960                    }
961                    else {
962                            return false;
963                    }
964            }
965    
966            private static final int _CHAR_BEGIN = 65;
967    
968            private static final int _CHAR_END = 122;
969    
970            private static final int _DIGIT_BEGIN = 48;
971    
972            private static final int _DIGIT_END = 57;
973    
974            private static final char[] _EMAIL_ADDRESS_SPECIAL_CHAR = new char[] {
975                    '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^',
976                    '_', '`', '{', '|', '}', '~'
977            };
978    
979            private static final String _LOCALHOST = "localhost";
980    
981            private static final String _VARIABLE_TERM_BEGIN = "[$";
982    
983            private static final String _VARIABLE_TERM_END = "$]";
984    
985            private static final String _XML_BEGIN = "<?xml";
986    
987            private static final String _XML_EMPTY = "<root />";
988    
989            private static Pattern _emailAddressPattern = Pattern.compile(
990                    "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@" +
991                    "(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?");
992            private static Pattern _ipAddressPattern = Pattern.compile(
993                    "\\b" +
994                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
995                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
996                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\." +
997                    "((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])" +
998                    "\\b");
999            private static Pattern _variableNamePattern = Pattern.compile(
1000                    "[_a-zA-Z]+[_a-zA-Z0-9]*");
1001    
1002    }