Thursday, March 20, 2008

How to Compare Two Date using JSF ?

Generally we want to compare the two date like any starting date or ending date.

Like ending date should greater than Start Date,
Ending Date should Greater or Equal to Start Date and many more..

For that we need write some bits of coding in JSF, Or Seam.
Here below code snippets guide you to perform your desired above operation.

1. First need to write your custom DateValidator which will perform your operation.

package com.joshi.validator;

    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import javax.faces.application.FacesMessage;
    import javax.faces.component.UIComponent;
    import javax.faces.component.html.HtmlInputText;
    import javax.faces.context.FacesContext;
    import javax.faces.validator.Validator;
    import javax.faces.validator.ValidatorException;
    import javax.swing.text.html.HTML;

  /**
  * @author Shirin Joshi 
  * Here operator: 
  *   gt for Greater Than 
  *   lt for Less Than
  *      eq for EqualTo 
  *      gq for Greater and Equal To 
  *      lq for Less and Equal To 
  *      nt for Not Equal To
  * 
  */

public class DateCompareValidator implements Validator {

    private String operator = "";

    private Date compareWith = new Date();

    private String compareFieldName = "";

  /*
  * @see javax.faces.validator.Validator#validate(javax.faces.context.FacesContext,
  *      javax.faces.component.UIComponent, java.lang.Object)
  */

    public void validate(FacesContext context, UIComponent component,Object value) 
    throws ValidatorException {

     boolean isVailid = true;
 
     System.out.println("=============");
     System.out.println("value :: " + value);

     initProps(component, context);
 
     System.out.println("operator :: " + operator);
     System.out.println("compareWith :: " + compareWith);
     System.out.println("compareFieldName :: " + compareFieldName);
     System.out.println("=============");

     FacesMessage message = new FacesMessage();
     Date thisDate = null;

     try {
      thisDate = (Date) value;
     } catch (Exception e) {
      System.out.println("Error in validate method of DateCompareValidator : " + e);
     }

     if (thisDate == null) {
      thisDate = new Date();
     }

     int result = thisDate.compareTo(compareWith);

     String compareData = "";

     if (compareFieldName.trim().length() != 0) {
      compareData = compareFieldName;
     } else {
      compareData = new SimpleDateFormat("MM/dd/yyyy").format(compareWith);

     }

   /*
   * required >= and we found the result less than
   */
 
     if (result < 0 && operator.equalsIgnoreCase("ge")  ) {
      message.setDetail("This date should >= " + compareData);
      message.setSummary("This date should >= " + compareData);
      isVailid = false;
     } else
 
   /*
   * required <= and we found the result greater than
   */
 
     if (result > 0 && operator.equalsIgnoreCase("le")) {
      message.setDetail("This date should <= " + compareData);
      message.setSummary("This date should <= " + compareData);
      isVailid = false;
     } else
 
   /*
   * required == and we found the result not equal
   */
 
     if (result != 0 && operator.equalsIgnoreCase("eq")) {
      message.setDetail("This date should == " + compareData);
      message.setSummary("This date should == " + compareData);
      isVailid = false;
     } else
 
   /*
   * required > and we found the result less than equal too
   */
 
     if (result <= 0 && operator.equalsIgnoreCase("gt")) {
      message.setDetail("This date should > " + compareData);
      message.setSummary("This date should > " + compareData);
      isVailid = false;
     } else
 
   /*
   * required <>
   */
 
     if (result >= 0 && operator.equalsIgnoreCase("lt")) {
      message.setDetail("This date should < " + compareData);
      message.setSummary("This date should < " + compareData);
      isVailid = false;
     }else
 
   /*
   * required != and we found the result equal too
   */
 
     if (result == 0 && operator.equalsIgnoreCase("nt")) {
      message.setDetail("This date should not = " + compareData);
      message.setSummary("This date should not = " + compareData);
      isVailid = false;
     }
 
     
     if (!isVailid) {
      message.setSeverity(FacesMessage.SEVERITY_ERROR);
      throw new ValidatorException(message);
     }
    }

  /*
  * This method will set the value of both operator and date to compare.
  */

    private void initProps(UIComponent component, FacesContext context) {

     Object compareWith = component.getAttributes().get("compareWith");
 
     HtmlInputText ht = (HtmlInputText) context.getViewRoot().findComponent(compareWith.toString());

     if (ht != null) {
      compareWith = ht.getValue();
     }

     System.out.println("compareWith -----------::: " + compareWith);
     operator = (String) component.getAttributes().get("operator");
     if (operator == null) {
      operator = ">";
     }

     compareFieldName = (String) component.getAttributes().get("compareFieldName");
     if (compareWith != null) {
      try {
       this.compareWith = (Date) compareWith;
      } catch (Exception e) {
       System.out.println("Error in parsing the Date : " + e);
      }
     }

    }
}

2. Now need to register your validator to Faces so for that open faces-config.xml and add following lines.

<validator>
 <validator-id>DateCompareValidatorvalidator-id>
 <validator-class>
  com.joshi.validator.DateCompareValidator
 <validator-class>
<validator>

3. Now if you have the start date

<s:decorate id="startDateDecoration" template="/layout/edit.xhtml">
 <ui:define name="label">
  #{messages['startDate']}
 </ui:define>
 <h:inputText id="startDate" required="true" value="#{bean.startDate}">
  <s:convertDateTime pattern="MM/dd/yyyy" />
 </h:inputText>
 <s:selectDate for="startDate" startYear="1910" endYear="2007">
  <img src="http://localhost:8080/mcc/img/dtpick.gif" />
 </s:selectDate>
</s:decorate>

4. And end Date with following

<s:decorate id="endDateDecoration" template="/layout/edit.xhtml">
 <ui:define name="label">
 #{messages['endDate']}
 </ui:define>
 
 <h:inputText id="endDate" required="true" value="#{bean.endDate}">
  <s:convertDateTime pattern="MM/dd/yyyy" />
  <f:validator validatorId="DateCompareValidator"/>
  <f:attribute name="operator" value="ge" />
  <f:attribute name="compareWith" value="FormName:startDateDecoration:startDate"/>
  <f:attribute name="compareFieldName" value="Start Date"/>
 </h:inputText>
 
 <s:selectDate for="endDate" startYear="1910" endYear="2007">
  <img src="http://localhost:8080/mcc/img/dtpick.gif" />
 </s:selectDate>
</s:decorate>

And your application work with your date Validation..
<f:validator validatorId="DateCompareValidator"/>

Above line add the Validator to out input Text
<f:attribute name="operator" value="ge" />
Above line set the operator you can use gt,lt,le,eq,nt respectivally for >,<,<=,==,!=.
<f:attribute name="compareWith" value="FormName:startDateDecoration:startDate"/>

Above line need to set bye you as per the id generated for your start date in HTML code.
<f:attribute name="compareFieldName" value="Start Date"/>

Above line need to set bye you it will used to Generate the Error Message i.e.
This Field should Start Date

In this case it will this Field should > Start Date

3 comments:

Unknown said...

Thank you

Anonymous said...

Fantastic job!
Thanks

Mounir Messelmeni said...

Thanks, very good example, it helps me :)

Contributors