/* SimpleDateConstraint.java Purpose: Description: History: Tue Dec 25 12:06:30 2007, Created by tomyeh Copyright (C) 2007 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.zul; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Pattern; import org.zkoss.util.Dates; import org.zkoss.util.Locales; import org.zkoss.util.TimeZones; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.UiException; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zul.mesg.MZul; /** * A simple date constraint. * * @author tomyeh * @since 3.0.2 */ public class SimpleDateConstraint extends SimpleConstraint { private Date _beg, _end; public SimpleDateConstraint(int flags) { super(flags); fixConstraint(); } /** Constraints a constraint. * * @param flags a combination of {@link #NO_POSITIVE}, {@link #NO_NEGATIVE}, * {@link #NO_ZERO}, and so on. * @param errmsg the error message to display. Ignored if null or empty. */ public SimpleDateConstraint(int flags, String errmsg) { super(flags, errmsg); fixConstraint(); } /** Constructs a regular-expression constraint. * * @param regex ignored if null or empty. Unlike constraint, the regex doesn't need to enclose with '/'. * @param errmsg the error message to display. Ignored if null or empty. * @deprecated As of release 8.0.1, replaced with {@link #SimpleDateConstraint(Pattern, String)} */ public SimpleDateConstraint(String regex, String errmsg) { super(regex == null || regex.length() == 0 ? null : Pattern.compile(regex), errmsg); fixConstraint(); } /** Constructs a regular-expression constraint. * * @param regex ignored if null or empty * @param errmsg the error message to display. Ignored if null or empty. * @since 8.0.1 */ public SimpleDateConstraint(Pattern regex, String errmsg) { super(regex, errmsg); fixConstraint(); } /** Constructs a constraint combining regular expression. * * @param flags a combination of {@link #NO_POSITIVE}, {@link #NO_NEGATIVE}, * {@link #NO_ZERO}, and so on. * @param regex ignored if null or empty. Unlike constraint, the regex doesn't need to enclose with '/'. * @param errmsg the error message to display. Ignored if null or empty. * @deprecated As of release 8.0.1, replaced with {@link #SimpleDateConstraint(int, Pattern, String)} */ public SimpleDateConstraint(int flags, String regex, String errmsg) { super(flags, regex == null || regex.length() == 0 ? null : Pattern.compile(regex), errmsg); fixConstraint(); } /** Constructs a constraint combining regular expression. * * @param flags a combination of {@link #NO_POSITIVE}, {@link #NO_NEGATIVE}, * {@link #NO_ZERO}, and so on. * @param regex ignored if null or empty * @param errmsg the error message to display. Ignored if null or empty. * @since 8.0.1 */ public SimpleDateConstraint(int flags, Pattern regex, String errmsg) { super(flags, regex, errmsg); fixConstraint(); } /** Constructs a constraint with beginning and ending date. * * @param flags a combination of {@link #NO_POSITIVE}, {@link #NO_NEGATIVE}, * {@link #NO_ZERO}, and so on. * @param begin the beginning date, or null if no constraint at the beginning * date. * @param end the ending date, or null if no constraint at the ending * date. * @param errmsg the error message to display. Ignored if null or empty. */ public SimpleDateConstraint(int flags, Date begin, Date end, String errmsg) { super(flags, errmsg); _beg = begin; _end = end; fixConstraint(); } /** Constructs a constraint with a list of constraints separated by comma. * * @param constraint a list of constraints separated by comma. * Example: "between 20071012 and 20071223", "before 20080103" */ public SimpleDateConstraint(String constraint) { super(constraint); fixConstraint(); } private void fixConstraint() { if ((_flags & NO_FUTURE) != 0 && _end == null) _end = Dates.today(); if ((_flags & NO_PAST) != 0 && _beg == null) _beg = Dates.today(); } /** Returns the beginning date, or null if there is no constraint of * the beginning date. */ public Date getBeginDate() { return _beg; } /** Returns the ending date, or null if there is no constraint of * the ending date. */ public Date getEndDate() { return _end; } //super// protected int parseConstraint(String constraint) throws UiException { if (constraint.startsWith("between")) { final int j = constraint.indexOf("and", 7); if (j < 0) throw new UiException("Constraint syntax error: " + constraint); _beg = parseDate(constraint.substring(7, j)); _end = parseDate(constraint.substring(j + 3)); if (_beg.compareTo(_end) > 0) { final Date d = _beg; _beg = _end; _end = d; } return 0; } else if (constraint.startsWith("before") && !constraint.startsWith("before_")) { _end = parseDate(constraint.substring(6)); return 0; } else if (constraint.startsWith("after") && !constraint.startsWith("after_")) { _beg = parseDate(constraint.substring(5)); return 0; } return super.parseConstraint(constraint); } private static Date parseDate(String val) throws UiException { try { return getDateFormat().parse(val.trim()); } catch (ParseException ex) { throw new UiException("Not a date: " + val + ". Format: yyyyMMdd", ex); } } private static SimpleDateFormat getDateFormat() { SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd", Locales.getCurrent()); df.setTimeZone(TimeZones.getCurrent()); return df; } public void validate(Component comp, Object value) throws WrongValueException { if (value instanceof Date) { final Date d = Dates.beginOfDate((Date) value, TimeZones.getCurrent()); if (_beg != null && _beg.compareTo(d) > 0) throw outOfRangeValue(comp); if (_end != null && _end.compareTo(d) < 0) throw outOfRangeValue(comp); } super.validate(comp, value); } private WrongValueException outOfRangeValue(Component comp) { final String errmsg = getErrorMessage(comp); if (errmsg != null) return new WrongValueException(comp, errmsg); final String s = _beg != null ? _end != null ? dateToString(comp, _beg) + " ~ " + dateToString(comp, _end) : ">= " + dateToString(comp, _beg) : "<= " + dateToString(comp, _end); return new WrongValueException(comp, MZul.OUT_OF_RANGE, s); } private static String dateToString(Component comp, Date d) { if (d == null) return ""; if (comp instanceof Datebox) return ((Datebox) comp).coerceToString(d); return getDateFormat().format(d); } }