protected void setupDefinition(Element widgetElement, FieldDefinition definition)
      throws Exception {
    super.setupDefinition(widgetElement, definition);

    // parse "@required"
    boolean required = DomHelper.getAttributeAsBoolean(widgetElement, "required", false);
    definition.setRequired(required);

    // parse "@length"
    int length = DomHelper.getAttributeAsInteger(widgetElement, "length", 7);
    ((CaptchaFieldDefinition) definition).setLength(length);
  }
  public ValidationRule build(Element validationRuleElement) throws Exception {
    ValueCountValidationRule rule = new ValueCountValidationRule();

    String exactExprString = validationRuleElement.getAttribute("exact");
    String minExprString = validationRuleElement.getAttribute("min");
    String maxExprString = validationRuleElement.getAttribute("max");

    if (exactExprString.length() > 0) {
      Expression expression = parseExpression(exactExprString, validationRuleElement, "exact");
      rule.setExactExpr(expression);
    } else if (minExprString.length() > 0 && maxExprString.length() > 0) {
      Expression expression = parseExpression(minExprString, validationRuleElement, "min");
      rule.setMinExpr(expression);
      expression = parseExpression(maxExprString, validationRuleElement, "max");
      rule.setMaxExpr(expression);
    } else if (minExprString.length() > 0) {
      Expression expression = parseExpression(minExprString, validationRuleElement, "min");
      rule.setMinExpr(expression);
    } else if (maxExprString.length() > 0) {
      Expression expression = parseExpression(maxExprString, validationRuleElement, "max");
      rule.setMaxExpr(expression);
    } else {
      throw new Exception(
          "value-count validation rule requires a min and/or max, or exact attribute at "
              + DomHelper.getLocation(validationRuleElement));
    }

    buildFailMessage(validationRuleElement, rule);

    return rule;
  }
  public WidgetListener buildListener(Element element, Class listenerClass) throws Exception {

    String name = DomHelper.getAttribute(element, "class");

    Object listener = ClassUtils.newInstance(name);
    if (listenerClass.isAssignableFrom(listener.getClass())) {
      LifecycleHelper.setupComponent(listener, null, null, manager, null);
      return (WidgetListener) listener;
    } else {
      throw new Exception("Class " + listener.getClass() + " is not a " + listenerClass);
    }
  }
  public Convertor build(Element configElement) throws Exception {
    FormattingDateConvertor convertor = new FormattingDateConvertor();

    if (configElement == null) return convertor;

    String style = configElement.getAttribute("style");
    if (!style.equals("")) {
      if (style.equals("short")) convertor.setStyle(DateFormat.SHORT);
      else if (style.equals("medium")) convertor.setStyle(DateFormat.MEDIUM);
      else if (style.equals("long")) convertor.setStyle(DateFormat.LONG);
      else if (style.equals("full")) convertor.setStyle(DateFormat.FULL);
      else
        throw new Exception(
            "Invalid value \""
                + style
                + "\" for style attribute at "
                + DomHelper.getLocation(configElement));
    }

    String variant = configElement.getAttribute("variant");
    if (!variant.equals("")) {
      if (variant.equals(FormattingDateConvertor.DATE)
          || variant.equals(FormattingDateConvertor.TIME)
          || variant.equals(FormattingDateConvertor.DATE_TIME)) {
        convertor.setVariant(variant);
      } else {
        throw new Exception(
            "Invalid value \""
                + variant
                + "\" for variant attribute at "
                + DomHelper.getLocation(configElement));
      }
    }

    String lenient = configElement.getAttribute("lenient");
    if (!lenient.equals("")) {
      if (lenient.equals("false") || lenient.equals("no")) {
        convertor.setLenient(false);
      } else if (lenient.equals("true") || lenient.equals("yes")) {
        convertor.setLenient(true);
      } else {
        throw new Exception(
            "Invalid value \""
                + lenient
                + "\" for lenient attribute at "
                + DomHelper.getLocation(configElement));
      }
    }

    Element patternsEl =
        DomHelper.getChildElement(configElement, FormsConstants.DEFINITION_NS, "patterns", false);
    if (patternsEl != null) {
      Element patternEl[] =
          DomHelper.getChildElements(patternsEl, FormsConstants.DEFINITION_NS, "pattern");
      for (int i = 0; i < patternEl.length; i++) {
        String locale = patternEl[i].getAttribute("locale");
        String pattern = DomHelper.getElementText(patternEl[i]);
        if (pattern.length() == 0)
          throw new Exception(
              "pattern element does not contain any content at "
                  + DomHelper.getLocation(patternEl[i]));
        if (locale.length() == 0) convertor.setNonLocalizedPattern(pattern);
        else {
          Locale loc = I18nUtils.parseLocale(locale);
          convertor.addFormattingPattern(loc, pattern);
        }
      }
    }

    return convertor;
  }