/**
  * Gets the appropriate CSS class to use based on the state of the current {@link
  * org.springframework.web.servlet.support.BindStatus} object.
  */
 protected String resolveCssClass() throws JspException {
   if (getBindStatus().isError() && StringUtils.hasText(getCssErrorClass())) {
     return ObjectUtils.getDisplayString(evaluate("cssErrorClass", getCssErrorClass()));
   } else {
     return ObjectUtils.getDisplayString(evaluate("cssClass", getCssClass()));
   }
 }
  /** Copy & Paste, 无修正. */
  @Override
  protected int writeTagContent(TagWriter tagWriter) throws JspException {
    Object items = getItems();
    Object itemsObject = items instanceof String ? evaluate("items", items) : items;

    String itemValue = getItemValue();
    String itemLabel = getItemLabel();
    String valueProperty =
        itemValue != null ? ObjectUtils.getDisplayString(evaluate("itemValue", itemValue)) : null;
    String labelProperty =
        itemLabel != null ? ObjectUtils.getDisplayString(evaluate("itemLabel", itemLabel)) : null;

    Class<?> boundType = getBindStatus().getValueType();
    if ((itemsObject == null) && (boundType != null) && boundType.isEnum()) {
      itemsObject = boundType.getEnumConstants();
    }

    if (itemsObject == null) {
      throw new IllegalArgumentException(
          "Attribute 'items' is required and must be a Collection, an Array or a Map");
    }

    if (itemsObject.getClass().isArray()) {
      Object[] itemsArray = (Object[]) itemsObject;
      for (int i = 0; i < itemsArray.length; i++) {
        Object item = itemsArray[i];
        writeObjectEntry(tagWriter, valueProperty, labelProperty, item, i);
      }
    } else if (itemsObject instanceof Collection) {
      final Collection<?> optionCollection = (Collection<?>) itemsObject;
      int itemIndex = 0;
      for (Iterator<?> it = optionCollection.iterator(); it.hasNext(); itemIndex++) {
        Object item = it.next();
        writeObjectEntry(tagWriter, valueProperty, labelProperty, item, itemIndex);
      }
    } else if (itemsObject instanceof Map) {
      final Map<?, ?> optionMap = (Map<?, ?>) itemsObject;
      int itemIndex = 0;
      for (Iterator<?> it = optionMap.entrySet().iterator(); it.hasNext(); itemIndex++) {
        @SuppressWarnings("rawtypes")
        Map.Entry entry = (Map.Entry) it.next();
        writeMapEntry(tagWriter, valueProperty, labelProperty, entry, itemIndex);
      }
    } else {
      throw new IllegalArgumentException(
          "Attribute 'items' must be an array, a Collection or a Map");
    }

    return SKIP_BODY;
  }
  /**
   * Writes the optional attributes configured via this base class to the supplied {@link
   * TagWriter}. The set of optional attributes that will be rendered includes any non-standard
   * dynamic attributes. Called by {@link #writeDefaultAttributes(TagWriter)}.
   */
  protected void writeOptionalAttributes(TagWriter tagWriter) throws JspException {
    tagWriter.writeOptionalAttributeValue(CLASS_ATTRIBUTE, resolveCssClass());
    tagWriter.writeOptionalAttributeValue(
        STYLE_ATTRIBUTE, ObjectUtils.getDisplayString(evaluate("cssStyle", getCssStyle())));
    writeOptionalAttribute(tagWriter, LANG_ATTRIBUTE, getLang());
    writeOptionalAttribute(tagWriter, TITLE_ATTRIBUTE, getTitle());
    writeOptionalAttribute(tagWriter, DIR_ATTRIBUTE, getDir());
    writeOptionalAttribute(tagWriter, TABINDEX_ATTRIBUTE, getTabindex());
    writeOptionalAttribute(tagWriter, ONCLICK_ATTRIBUTE, getOnclick());
    writeOptionalAttribute(tagWriter, ONDBLCLICK_ATTRIBUTE, getOndblclick());
    writeOptionalAttribute(tagWriter, ONMOUSEDOWN_ATTRIBUTE, getOnmousedown());
    writeOptionalAttribute(tagWriter, ONMOUSEUP_ATTRIBUTE, getOnmouseup());
    writeOptionalAttribute(tagWriter, ONMOUSEOVER_ATTRIBUTE, getOnmouseover());
    writeOptionalAttribute(tagWriter, ONMOUSEMOVE_ATTRIBUTE, getOnmousemove());
    writeOptionalAttribute(tagWriter, ONMOUSEOUT_ATTRIBUTE, getOnmouseout());
    writeOptionalAttribute(tagWriter, ONKEYPRESS_ATTRIBUTE, getOnkeypress());
    writeOptionalAttribute(tagWriter, ONKEYUP_ATTRIBUTE, getOnkeyup());
    writeOptionalAttribute(tagWriter, ONKEYDOWN_ATTRIBUTE, getOnkeydown());

    if (!CollectionUtils.isEmpty(this.dynamicAttributes)) {
      for (String attr : this.dynamicAttributes.keySet()) {
        tagWriter.writeOptionalAttributeValue(
            attr, getDisplayString(this.dynamicAttributes.get(attr)));
      }
    }
  }
  protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
    if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
      // The application context id is still set to its original default value
      // -> assign a more useful id based on available information
      if (this.contextId != null) {
        wac.setId(this.contextId);
      } else {
        // Generate default id...
        wac.setId(
            ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX
                + ObjectUtils.getDisplayString(getServletContext().getContextPath())
                + "/"
                + getServletName());
      }
    }

    wac.setServletContext(getServletContext());
    wac.setServletConfig(getServletConfig());
    wac.setNamespace(getNamespace());
    wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));

    // The wac environment's #initPropertySources will be called in any case when the context
    // is refreshed; do it eagerly here to ensure servlet property sources are in place for
    // use in any post-processing or initialization that occurs below prior to #refresh
    ConfigurableEnvironment env = wac.getEnvironment();
    if (env instanceof ConfigurableWebEnvironment) {
      ((ConfigurableWebEnvironment) env)
          .initPropertySources(getServletContext(), getServletConfig());
    }

    postProcessWebApplicationContext(wac);
    applyInitializers(wac);
    wac.refresh();
  }