static Date getDate(TemplateDateModel model, Expression expr, Environment env)
     throws TemplateModelException, TemplateException {
   Date value = model.getAsDate();
   if (value == null) {
     throw new TemplateException(expr + " evaluated to null date.", env);
   }
   return value;
 }
 /*
  * WARNING! This algorithm is duplicated in SequenceBuiltins.modelsEqual.
  * Thus, if you update this method, then you have to update that too!
  */
 boolean isTrue(Environment env) throws TemplateException {
   TemplateModel ltm = left.getAsTemplateModel(env);
   TemplateModel rtm = right.getAsTemplateModel(env);
   if (env != null && env.isClassicCompatible()) {
     if (ltm == null) {
       ltm = TemplateScalarModel.EMPTY_STRING;
     }
     if (rtm == null) {
       rtm = TemplateScalarModel.EMPTY_STRING;
     }
   }
   assertNonNull(ltm, left, env);
   assertNonNull(rtm, right, env);
   int comp = 0;
   if (ltm instanceof TemplateNumberModel && rtm instanceof TemplateNumberModel) {
     Number first = EvaluationUtil.getNumber((TemplateNumberModel) ltm, left, env);
     Number second = EvaluationUtil.getNumber((TemplateNumberModel) rtm, right, env);
     ArithmeticEngine ae =
         env != null ? env.getArithmeticEngine() : getTemplate().getArithmeticEngine();
     comp = ae.compareNumbers(first, second);
   } else if (ltm instanceof TemplateDateModel && rtm instanceof TemplateDateModel) {
     TemplateDateModel ltdm = (TemplateDateModel) ltm;
     TemplateDateModel rtdm = (TemplateDateModel) rtm;
     int ltype = ltdm.getDateType();
     int rtype = rtdm.getDateType();
     if (ltype != rtype) {
       throw new TemplateException(
           "Can not compare dates of different type. Left date is of "
               + TemplateDateModel.TYPE_NAMES.get(ltype)
               + " type, right date is of "
               + TemplateDateModel.TYPE_NAMES.get(rtype)
               + " type.",
           env);
     }
     if (ltype == TemplateDateModel.UNKNOWN) {
       throw new TemplateException("Left date is of UNKNOWN type, and can not be compared.", env);
     }
     if (rtype == TemplateDateModel.UNKNOWN) {
       throw new TemplateException("Right date is of UNKNOWN type, and can not be compared.", env);
     }
     Date first = EvaluationUtil.getDate(ltdm, left, env);
     Date second = EvaluationUtil.getDate(rtdm, right, env);
     comp = first.compareTo(second);
   } else if (ltm instanceof TemplateScalarModel && rtm instanceof TemplateScalarModel) {
     if (operation != EQUALS && operation != NOT_EQUALS) {
       throw new TemplateException("Can not use operator " + opString + " on string values.", env);
     }
     String first = EvaluationUtil.getString((TemplateScalarModel) ltm, left, env);
     String second = EvaluationUtil.getString((TemplateScalarModel) rtm, right, env);
     comp = env.getCollator().compare(first, second);
   } else if (ltm instanceof TemplateBooleanModel && rtm instanceof TemplateBooleanModel) {
     if (operation != EQUALS && operation != NOT_EQUALS) {
       throw new TemplateException(
           "Can not use operator " + opString + " on boolean values.", env);
     }
     boolean first = ((TemplateBooleanModel) ltm).getAsBoolean();
     boolean second = ((TemplateBooleanModel) rtm).getAsBoolean();
     comp = (first ? 1 : 0) - (second ? 1 : 0);
   }
   // Here we handle compatibility issues
   else if (env.isClassicCompatible()) {
     String first = left.getStringValue(env);
     String second = right.getStringValue(env);
     comp = env.getCollator().compare(first, second);
   } else {
     throw new TemplateException(
         "The only legal comparisons are between two numbers, two strings, or two dates.\n"
             + "Left  hand operand is a "
             + ltm.getClass().getName()
             + "\n"
             + "Right hand operand is a "
             + rtm.getClass().getName()
             + "\n",
         env);
   }
   switch (operation) {
     case EQUALS:
       return comp == 0;
     case NOT_EQUALS:
       return comp != 0;
     case LESS_THAN:
       return comp < 0;
     case GREATER_THAN:
       return comp > 0;
     case LESS_THAN_EQUALS:
       return comp <= 0;
     case GREATER_THAN_EQUALS:
       return comp >= 0;
     default:
       throw new TemplateException("unknown operation", env);
   }
 }