001: /*
002: * Copyright (c) 2003-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.validation.util;
032:
033: import java.util.Calendar;
034: import java.util.Date;
035: import java.util.GregorianCalendar;
036:
037: /**
038: * Consists exclusively of static methods for validating input values
039: * by testing and comparing single and multiple values.<p>
040: *
041: * The <a href="http://jakarta.apache.org/commons/lang.html">Jakarta Commons Lang</a>
042: * library contains more classes and methods useful for validation.
043: * The Utils string and character tests in this ValidationUtils class are
044: * compatible with the Jakarta Commons Lang <code>StringUtils</code> methods.
045: *
046: * @author Karsten Lentzsch
047: * @version $Revision: 1.12 $
048: *
049: * @see Calendar
050: */
051: public final class ValidationUtils {
052:
053: private ValidationUtils() {
054: // Override default constructor; prevents instantiation.
055: }
056:
057: // Object Comparison ******************************************************
058:
059: /**
060: * Checks and answers if the two objects are
061: * both <code>null</code> or equal.
062: *
063: * <pre>
064: * ValidationUtils.equals(null, null) == true
065: * ValidationUtils.equals("Hi", "Hi") == true
066: * ValidationUtils.equals("Hi", null) == false
067: * ValidationUtils.equals(null, "Hi") == false
068: * ValidationUtils.equals("Hi", "Ho") == false
069: * </pre>
070: *
071: * @param o1 the first object to compare
072: * @param o2 the second object to compare
073: * @return boolean <code>true</code> if and only if
074: * both objects are <code>null</code> or equal
075: */
076: public static boolean equals(Object o1, Object o2) {
077: return (o1 != null && o2 != null && o1.equals(o2))
078: || (o1 == null && o2 == null);
079: }
080:
081: // String Validations ***************************************************
082:
083: /**
084: * Checks and answers if the given string is whitespace,
085: * empty ("") or <code>null</code>.
086: *
087: * <pre>
088: * ValidationUtils.isBlank(null) == true
089: * ValidationUtils.isBlank("") == true
090: * ValidationUtils.isBlank(" ") == true
091: * ValidationUtils.isBlank(" abc") == false
092: * ValidationUtils.isBlank("abc ") == false
093: * ValidationUtils.isBlank(" abc ") == false
094: * </pre>
095: *
096: * @param str the string to check, may be <code>null</code>
097: * @return <code>true</code> if the string is whitespace, empty
098: * or <code>null</code>
099: *
100: * @see #isEmpty(String)
101: */
102: public static boolean isBlank(String str) {
103: int length;
104: if ((str == null) || ((length = str.length()) == 0)) {
105: return true;
106: }
107: for (int i = length - 1; i >= 0; i--) {
108: if (!Character.isWhitespace(str.charAt(i))) {
109: return false;
110: }
111: }
112: return true;
113: }
114:
115: /**
116: * Checks and answers if the given string is not empty (""),
117: * not <code>null</code> and not whitespace only.
118: *
119: * <pre>
120: * ValidationUtils.isNotBlank(null) == false
121: * ValidationUtils.isNotBlank("") == false
122: * ValidationUtils.isNotBlank(" ") == false
123: * ValidationUtils.isNotBlank(" abc") == true
124: * ValidationUtils.isNotBlank("abc ") == true
125: * ValidationUtils.isNotBlank(" abc ") == true
126: * </pre>
127: *
128: * @param str the string to check, may be <code>null</code>
129: * @return <code>true</code> if the string is not empty
130: * and not <code>null</code> and not whitespace only
131: *
132: * @see #isEmpty(String)
133: *
134: * @since 1.2
135: */
136: public static boolean isNotBlank(String str) {
137: int length;
138: if ((str == null) || ((length = str.length()) == 0)) {
139: return false;
140: }
141: for (int i = length - 1; i >= 0; i--) {
142: if (!Character.isWhitespace(str.charAt(i))) {
143: return true;
144: }
145: }
146: return false;
147: }
148:
149: /**
150: * Checks and answers if the given string is empty ("") or <code>null</code>.
151: *
152: * <pre>
153: * ValidationUtils.isEmpty(null) == true
154: * ValidationUtils.isEmpty("") == true
155: * ValidationUtils.isEmpty(" ") == false
156: * ValidationUtils.isEmpty("Hi ") == false
157: * </pre>
158: *
159: * @param str the string to check, may be <code>null</code>
160: * @return <code>true</code> if the string is empty or <code>null</code>
161: *
162: * @see #isBlank(String)
163: */
164: public static boolean isEmpty(String str) {
165: return (str == null) || (str.length() == 0);
166: }
167:
168: /**
169: * Checks and answers if the given string is not empty ("")
170: * and not <code>null</code>.
171: *
172: * <pre>
173: * ValidationUtils.isNotEmpty(null) == false
174: * ValidationUtils.isNotEmpty("") == false
175: * ValidationUtils.isNotEmpty(" ") == true
176: * ValidationUtils.isNotEmpty("Hi") == true
177: * ValidationUtils.isNotEmpty("Hi ") == true
178: * </pre>
179: *
180: * @param str the string to check, may be <code>null</code>
181: * @return <code>true</code> if the string is not empty and not <code>null</code>
182: *
183: * @see #isBlank(String)
184: */
185: public static boolean isNotEmpty(String str) {
186: return (str != null) && (str.length() > 0);
187: }
188:
189: /**
190: * Checks and answers if the given string has at least the
191: * specified minimum length.
192: * Strings that are <code>null</code> or contain only blanks have length 0.
193: *
194: * <pre>
195: * ValidationUtils.hasMinimumLength(null, 2) == false
196: * ValidationUtils.hasMinimumLength("", 2) == false
197: * ValidationUtils.hasMinimumLength(" ", 2) == false
198: * ValidationUtils.hasMinimumLength(" ", 2) == false
199: * ValidationUtils.hasMinimumLength("Hi ", 2) == true
200: * ValidationUtils.hasMinimumLength("Ewa", 2) == true
201: * </pre>
202: *
203: * @param str the string to check
204: * @param min the minimum length
205: * @return <code>true</code> if the length is greater or equal to the minimum,
206: * <code>false</code> otherwise
207: */
208: public static boolean hasMinimumLength(String str, int min) {
209: int length = str == null ? 0 : str.trim().length();
210: return min <= length;
211: }
212:
213: /**
214: * Checks and answers if the given string is shorter than
215: * the specified maximum length.
216: * Strings that are <code>null</code> or contain only blanks have length 0.
217: *
218: * <pre>
219: * ValidationUtils.hasMaximumLength(null, 2) == true
220: * ValidationUtils.hasMaximumLength("", 2) == true
221: * ValidationUtils.hasMaximumLength(" ", 2) == true
222: * ValidationUtils.hasMaximumLength(" ", 2) == true
223: * ValidationUtils.hasMaximumLength("Hi ", 2) == true
224: * ValidationUtils.hasMaximumLength("Ewa", 2) == false
225: * </pre>
226: *
227: * @param str the string to check
228: * @param max the maximum length
229: * @return <code>true</code> if the length is less than or equal to the minimum,
230: * <code>false</code> otherwise
231: */
232: public static boolean hasMaximumLength(String str, int max) {
233: int length = str == null ? 0 : str.trim().length();
234: return length <= max;
235: }
236:
237: /**
238: * Checks and answers if the length of the given string is in the
239: * bounds as specified by the interval [min, max].
240: * Strings that are <code>null</code> or contain only blanks have length 0.
241: *
242: * <pre>
243: * ValidationUtils.hasBoundedLength(null, 1, 2) == false
244: * ValidationUtils.hasBoundedLength("", 1, 2) == false
245: * ValidationUtils.hasBoundedLength(" ", 1, 2) == false
246: * ValidationUtils.hasBoundedLength(" ", 1, 2) == false
247: * ValidationUtils.hasBoundedLength("Hi ", 1, 2) == true
248: * ValidationUtils.hasBoundedLength("Ewa", 1, 2) == false
249: * </pre>
250: *
251: * @param str the string to check
252: * @param min the minimum length
253: * @param max the maximum length
254: * @return <code>true</code> if the length is in the interval,
255: * <code>false</code> otherwise
256: * @throws IllegalArgumentException if min > max
257: */
258: public static boolean hasBoundedLength(String str, int min, int max) {
259: if (min > max) {
260: throw new IllegalArgumentException(
261: "The minimum length must be less than or equal to the maximum length.");
262: }
263: int length = str == null ? 0 : str.trim().length();
264: return (min <= length) && (length <= max);
265: }
266:
267: // Character Validations **************************************************
268:
269: /**
270: * Checks and answers if the given string contains only unicode letters.
271: * <code>null</code> returns false,
272: * an empty string ("") returns <code>true</code>.
273: *
274: * <pre>
275: * ValidationUtils.isAlpha(null) == false
276: * ValidationUtils.isAlpha("") == true
277: * ValidationUtils.isAlpha(" ") == false
278: * ValidationUtils.isAlpha("abc") == true
279: * ValidationUtils.isAlpha("ab c") == false
280: * ValidationUtils.isAlpha("ab2c") == false
281: * ValidationUtils.isAlpha("ab-c") == false
282: * </pre>
283: *
284: * @param str the string to check, may be <code>null</code>
285: * @return <code>true</code> if the string contains only unicode letters,
286: * and is non-<code>null</code>
287: *
288: * @since 1.2
289: */
290: public static boolean isAlpha(String str) {
291: if (str == null) {
292: return false;
293: }
294: for (int i = str.length() - 1; i >= 0; i--) {
295: if (!Character.isLetter(str.charAt(i))) {
296: return false;
297: }
298: }
299: return true;
300: }
301:
302: /**
303: * Checks and answers if the given string contains only unicode letters
304: * and space (' ').
305: * <code>null</code> returns false,
306: * an empty string ("") returns <code>true</code>.
307: *
308: * <pre>
309: * ValidationUtils.isAlphaSpace(null) == false
310: * ValidationUtils.isAlphaSpace("") == true
311: * ValidationUtils.isAlphaSpace(" ") == true
312: * ValidationUtils.isAlphaSpace("abc") == true
313: * ValidationUtils.isAlphaSpace("ab c") == true
314: * ValidationUtils.isAlphaSpace("ab2c") == false
315: * ValidationUtils.isAlphaSpace("ab-c") == false
316: * </pre>
317: *
318: * @param str the string to check, may be <code>null</code>
319: * @return <code>true</code> if the string contains only unicode letters
320: * and space, and is non-<code>null</code>
321: *
322: * @since 1.2
323: */
324: public static boolean isAlphaSpace(String str) {
325: if (str == null) {
326: return false;
327: }
328: for (int i = str.length() - 1; i >= 0; i--) {
329: char c = str.charAt(i);
330: if (!Character.isLetter(c) && (c != ' ')) {
331: return false;
332: }
333: }
334: return true;
335: }
336:
337: /**
338: * Checks and answers if the given string contains only
339: * unicode letters or digits.
340: * <code>null</code> returns false,
341: * an empty string ("") returns <code>true</code>.
342: *
343: * <pre>
344: * ValidationUtils.isAlphanumeric(null) == false
345: * ValidationUtils.isAlphanumeric("") == true
346: * ValidationUtils.isAlphanumeric(" ") == false
347: * ValidationUtils.isAlphanumeric("abc") == true
348: * ValidationUtils.isAlphanumeric("ab c") == false
349: * ValidationUtils.isAlphanumeric("ab2c") == true
350: * ValidationUtils.isAlphanumeric("ab-c") == false
351: * ValidationUtils.isAlphanumeric("123") == true
352: * ValidationUtils.isAlphanumeric("12 3") == false
353: * ValidationUtils.isAlphanumeric("12-3") == false
354: * </pre>
355: *
356: * @param str the string to check, may be <code>null</code>
357: * @return <code>true</code> if the string contains only unicode letters
358: * or digits, and is non-<code>null</code>
359: *
360: * @since 1.2
361: */
362: public static boolean isAlphanumeric(String str) {
363: if (str == null) {
364: return false;
365: }
366: for (int i = str.length() - 1; i >= 0; i--) {
367: if (!Character.isLetterOrDigit(str.charAt(i))) {
368: return false;
369: }
370: }
371: return true;
372: }
373:
374: /**
375: * Checks and answers if the given string contains only
376: * unicode letters or digits or space (' ').
377: * <code>null</code> returns false,
378: * an empty string ("") returns <code>true</code>.
379: *
380: * <pre>
381: * ValidationUtils.isAlphanumericSpace(null) == false
382: * ValidationUtils.isAlphanumericSpace("") == true
383: * ValidationUtils.isAlphanumericSpace(" ") == true
384: * ValidationUtils.isAlphanumericSpace("abc") == true
385: * ValidationUtils.isAlphanumericSpace("ab c") == true
386: * ValidationUtils.isAlphanumericSpace("ab2c") == true
387: * ValidationUtils.isAlphanumericSpace("ab-c") == false
388: * ValidationUtils.isAlphanumericSpace("123") == true
389: * ValidationUtils.isAlphanumericSpace("12 3") == true
390: * ValidationUtils.isAlphanumericSpace("12-3") == false
391: * </pre>
392: *
393: * @param str the string to check, may be <code>null</code>
394: * @return <code>true</code> if the string contains only unicode letters,
395: * digits or space (' '), and is non-<code>null</code>
396: *
397: * @since 1.2
398: */
399: public static boolean isAlphanumericSpace(String str) {
400: if (str == null) {
401: return false;
402: }
403: for (int i = str.length() - 1; i >= 0; i--) {
404: char c = str.charAt(i);
405: if (!Character.isLetterOrDigit(c) && (c != ' ')) {
406: return false;
407: }
408: }
409: return true;
410: }
411:
412: /**
413: * Checks and answers if the given string contains only unicode digits.
414: * A decimal point is not a unicode digit and returns <code>false</code>.
415: * <code>null</code> returns false,
416: * an empty string ("") returns <code>true</code>.
417: *
418: * <pre>
419: * ValidationUtils.isNumeric(null) == false
420: * ValidationUtils.isNumeric("") == true
421: * ValidationUtils.isNumeric(" ") == false
422: * ValidationUtils.isNumeric("abc") == false
423: * ValidationUtils.isNumeric("ab c") == false
424: * ValidationUtils.isNumeric("ab2c") == false
425: * ValidationUtils.isNumeric("ab-c") == false
426: * ValidationUtils.isNumeric("123") == true
427: * ValidationUtils.isNumeric("12 3") == false
428: * ValidationUtils.isNumeric("12-3") == false
429: * ValidationUtils.isNumeric("12.3") == false
430: * </pre>
431: *
432: * @param str the string to check, may be <code>null</code>
433: * @return <code>true</code> if the string contains only unicode digits,
434: * and is non-<code>null</code>
435: *
436: * @since 1.2
437: */
438: public static boolean isNumeric(String str) {
439: if (str == null) {
440: return false;
441: }
442: for (int i = str.length() - 1; i >= 0; i--) {
443: if (!Character.isDigit(str.charAt(i))) {
444: return false;
445: }
446: }
447: return true;
448: }
449:
450: /**
451: * Checks and answers if the given string contains only unicode digits
452: * or space (' '). A decimal point is not a unicode digit and
453: * returns <code>false</code>.
454: * <code>null</code> returns false,
455: * an empty string ("") returns <code>true</code>.
456: *
457: * <pre>
458: * ValidationUtils.isNumericSpace(null) == false
459: * ValidationUtils.isNumericSpace("") == true
460: * ValidationUtils.isNumericSpace(" ") == true
461: * ValidationUtils.isNumericSpace("abc") == false
462: * ValidationUtils.isNumericSpace("ab c") == false
463: * ValidationUtils.isNumericSpace("ab2c") == false
464: * ValidationUtils.isNumericSpace("ab-c") == false
465: * ValidationUtils.isNumericSpace("123") == true
466: * ValidationUtils.isNumericSpace("12 3") == true
467: * ValidationUtils.isNumericSpace("12-3") == false
468: * ValidationUtils.isNumericSpace("12.3") == false
469: * </pre>
470: *
471: * @param str the string to check, may be <code>null</code>
472: * @return <code>true</code> if the string contains only unicode digits
473: * or space, and is non-<code>null</code>
474: *
475: * @since 1.2
476: */
477: public static boolean isNumericSpace(String str) {
478: if (str == null) {
479: return false;
480: }
481: for (int i = str.length() - 1; i >= 0; i--) {
482: char c = str.charAt(i);
483: if (!Character.isDigit(c) && (c != ' ')) {
484: return false;
485: }
486: }
487: return true;
488: }
489:
490: // Date Validations *******************************************************
491:
492: /**
493: * Determines and answers if the day of the given <code>Date</code>
494: * is in the past.
495: *
496: * @param date the date to check
497: * @return <code>true</code> if in the past, <code>false</code> otherwise
498: */
499: public static boolean isPastDay(Date date) {
500: Calendar in = new GregorianCalendar();
501: in.setTime(date);
502: Calendar today = getRelativeCalendar(0);
503: return in.before(today);
504: }
505:
506: /**
507: * Determines and answers if the given <code>Date</code> is yesterday.
508: *
509: * @param date the date to check
510: * @return <code>true</code> if yesterday, <code>false</code> otherwise
511: */
512: public static boolean isYesterday(Date date) {
513: Calendar in = new GregorianCalendar();
514: in.setTime(date);
515: Calendar yesterday = getRelativeCalendar(-1);
516: Calendar today = getRelativeCalendar(0);
517: return !in.before(yesterday) && in.before(today);
518: }
519:
520: /**
521: * Determines and answers if the given <code>Date</code> is today.
522: *
523: * @param date the date to check
524: * @return <code>true</code> if today, <code>false</code> otherwise
525: */
526: public static boolean isToday(Date date) {
527: GregorianCalendar in = new GregorianCalendar();
528: in.setTime(date);
529: Calendar today = getRelativeCalendar(0);
530: Calendar tomorrow = getRelativeCalendar(+1);
531: return !in.before(today) && in.before(tomorrow);
532: }
533:
534: /**
535: * Determines and answers if the given <code>Date</code> is tomorrow.
536: *
537: * @param date the date to check
538: * @return <code>true</code> if tomorrow, <code>false</code> otherwise
539: */
540: public static boolean isTomorrow(Date date) {
541: GregorianCalendar in = new GregorianCalendar();
542: in.setTime(date);
543: Calendar tomorrow = getRelativeCalendar(+1);
544: Calendar dayAfter = getRelativeCalendar(+2);
545: return !in.before(tomorrow) && in.before(dayAfter);
546: }
547:
548: /**
549: * Determines and answers if the day of the given <code>Date</code>
550: * is in the future.
551: *
552: * @param date the date to check
553: * @return <code>true</code> if in the future, <code>false</code> otherwise
554: */
555: public static boolean isFutureDay(Date date) {
556: Calendar in = new GregorianCalendar();
557: in.setTime(date);
558: Calendar tomorrow = getRelativeCalendar(+1);
559: return !in.before(tomorrow);
560: }
561:
562: /**
563: * Computes the day that has the given offset in days to today
564: * and returns it as an instance of <code>Date</code>.
565: *
566: * @param offsetDays the offset in day relative to today
567: * @return the <code>Date</code> that is the begin of the day
568: * with the specified offset
569: */
570: public static Date getRelativeDate(int offsetDays) {
571: return getRelativeCalendar(offsetDays).getTime();
572: }
573:
574: /**
575: * Computes the day that has the given offset in days to today
576: * and returns it as an instance of <code>Calendar</code>.
577: *
578: * @param offsetDays the offset in day relative to today
579: * @return a <code>Calendar</code> instance that is the begin of the day
580: * with the specified offset
581: */
582: public static Calendar getRelativeCalendar(int offsetDays) {
583: Calendar today = new GregorianCalendar();
584: return getRelativeCalendar(today, offsetDays);
585: }
586:
587: /**
588: * Computes the day that has the given offset in days from the specified
589: * <em>from</em> date and returns it as an instance of <code>Calendar</code>.
590: *
591: * @param from the base date as <code>Calendar</code> instance
592: * @param offsetDays the offset in day relative to today
593: * @return a <code>Calendar</code> instance that is the begin of the day
594: * with the specified offset from the given day
595: */
596: public static Calendar getRelativeCalendar(Calendar from,
597: int offsetDays) {
598: Calendar temp = new GregorianCalendar(from.get(Calendar.YEAR),
599: from.get(Calendar.MONTH), from.get(Calendar.DATE), 0,
600: 0, 0);
601: temp.add(Calendar.DATE, offsetDays);
602: return temp;
603: }
604:
605: }
|