/** Helper to add a text widget set of render elements */
  private RenderElement addChoiceField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    CodedProperty prop = element instanceof CodedProperty ? (CodedProperty) element : null;

    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = null;
    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();

    if (prop.isUnbounded()) {
      ret = new DynamicFieldAttachment(wrapperType, "role-field", "combo");
      addAttribute(attrs, "searchUrl", new DynamicParameter(prop, "getSearchUrl"));
      getExtraAttributes(attrs, element, comboAttrs, "field");
      ret.setAttributes(attrs);
    } else if (prop.isDynamic()) {
      ret = new DynamicFieldAttachment(wrapperType, "role-field", "select");
      addAttribute(attrs, "searchUrl", new DynamicParameter(prop, "getSearchUrl"));
      getExtraAttributes(attrs, element, filterAttrs, "field");
      ret.setAttributes(attrs);
    } else {
      ret = new DynamicFieldAttachment(wrapperType, "role-field", "select");
      getExtraAttributes(attrs, element, filterAttrs, "field");
      ret.setAttributes(attrs);
    }

    return ret;
  }
  /** Helper to add a text widget set of render elements */
  private RenderElement addTextField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = new DynamicFieldAttachment(wrapperType, "role-field", "input");

    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
    getExtraAttributes(attrs, element, textAttrs, "field");
    ret.setAttributes(attrs);

    return ret;
  }
  /** Helper to add a text widget set of render elements */
  private RenderElement addBoolField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = new DynamicFieldAttachment(wrapperType, "role-field", "checkbox");

    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
    // Add in standard attrs if they exist
    getExtraAttributes(attrs, element, checkboxAttrs, "field");
    ret.setAttributes(attrs);

    return ret;
  }
  /** Helper to add a text widget set of render elements */
  private RenderElement addMemoField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = new DynamicFieldAttachment(wrapperType, "role-field", "memo");

    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
    if (element instanceof TextProperty) {
      addAttribute(attrs, "maxLength", new DynamicParameter(element, "getMaxLength"));
    }
    getExtraAttributes(attrs, element, memoAttrs, "field");
    ret.setAttributes(attrs);

    return ret;
  }
  /** Helper to add a text widget set of render elements */
  private RenderElement addNumberField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = new DynamicFieldAttachment(wrapperType, "role-field", "number");

    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
    if (element instanceof NumberProperty) {
      addAttribute(attrs, "min", new DynamicParameter(element, "getMinimum"));
      addAttribute(attrs, "max", new DynamicParameter(element, "getMinimum"));
      addAttribute(attrs, "places", new DynamicParameter(element, "getDecimalPlaces"));

      // TODO: If percentage, then set type
      // TODO: If currency, then set currency
      // TODO: Spinner!?!
    }
    getExtraAttributes(attrs, element, numberAttrs, "field");
    ret.setAttributes(attrs);

    return ret;
  }
  /** Helper to add a text widget set of render elements */
  private RenderElement addDateField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    DateProperty prop = element instanceof DateProperty ? (DateProperty) element : null;

    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment dt = null;
    DynamicFieldAttachment tm = null;

    if (prop == null || prop.isDate()) {
      dt = new DynamicFieldAttachment(wrapperType, "role-field", "date");
      Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
      if (prop != null)
        addAttribute(attrs, "formatLength", new DynamicParameter(element, "getDateFormat"));
      if (prop != null)
        addAttribute(attrs, "datePattern", new DynamicParameter(element, "getDatePattern"));

      getExtraAttributes(attrs, element, dateAttrs, "field");
      dt.setAttributes(attrs);
    }

    if (prop != null && prop.isTime()) {
      tm = new DynamicFieldAttachment(wrapperType, "role-timeField", "time");
      Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
      addAttribute(attrs, "formatLength", new DynamicParameter(element, "getTimeFormat"));
      addAttribute(attrs, "timePattern", new DynamicParameter(element, "getTimePattern"));

      getExtraAttributes(attrs, element, timeAttrs, "timeField");
      tm.setAttributes(attrs);
    }

    // Return one or both in a empty element
    if (tm == null) return dt;
    else if (dt == null) return tm;
    else {
      EmptyElement ret = new EmptyElement();
      ret.addElement(dt);
      ret.addElement(tm);
      return ret;
    }
  }
  /** Helper to add a validation widget set of render elements */
  private RenderElement addValidationField(
      GenericCompiler compiler, Template template, TemplateElement element) {
    TextProperty prop = element instanceof TextProperty ? (TextProperty) element : null;

    // If not a text prop, std text box
    if (prop == null) return addTextField(compiler, template, element);

    // If memo, treat as such
    if (prop.isMemo()) {
      return addMemoField(compiler, template, element);
    }

    String wrapperType = template.getName() + "-" + element.getName();
    DynamicFieldAttachment ret = new DynamicFieldAttachment(wrapperType, "role-field", "text");

    Map<String, RenderParameter> attrs = new HashMap<String, RenderParameter>();
    addAttribute(attrs, "maxLength", new DynamicParameter(prop, "getMaxLength"));
    addAttribute(attrs, "required", new DynamicParameter(prop, "isMandatory"));
    addAttribute(attrs, "regExp", new DynamicParameter(prop, "getValidationExpression"));
    getExtraAttributes(attrs, element, valAttrs, "field");
    ret.setAttributes(attrs);

    return ret;
  }