@Override @SuppressWarnings("rawtypes") protected void processTemplate(Template template, SimpleHash fmModel, HttpServletResponse response) throws TemplateException { Map model = fmModel.toMap(); assertTrue(model.get(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE) instanceof RequestContext); RequestContext rc = (RequestContext) model.get(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE); BindStatus status = rc.getBindStatus("tb.name"); assertEquals("name", status.getExpression()); assertEquals("juergen", status.getValue()); } };
Object boundValue = bindStatus.getValue(); if (ObjectUtils.nullSafeEquals(boundValue, candidateValue)) { return true; Object actualValue = bindStatus.getActualValue(); if (actualValue != null && actualValue != boundValue && ObjectUtils.nullSafeEquals(actualValue, candidateValue)) { selected = exhaustiveCompare(boundValue, candidateValue, bindStatus.getEditor(), null);
/** * Retrieve the Errors instance that this tag is currently bound to. * Intended for cooperating nesting tags. * @return the current Errors instance, or {@code null} if none */ @Nullable public final Errors getErrors() { return getStatus().getErrors(); }
/** * Returns '{@code true}' if the bound value requires the * resultant '{@code select}' tag to be multi-select. */ private boolean forceMultiple() throws JspException { BindStatus bindStatus = getBindStatus(); Class<?> valueType = bindStatus.getValueType(); if (valueType != null && typeRequiresMultiple(valueType)) { return true; } else if (bindStatus.getEditor() != null) { Object editorValue = bindStatus.getEditor().getValue(); if (editorValue != null && typeRequiresMultiple(editorValue.getClass())) { return true; } } return false; }
@Override protected void doProcess( final ITemplateContext context, final IProcessableElementTag tag, final AttributeName attributeName, final String attributeValue, final IElementTagStructureHandler structureHandler) { final BindStatus bindStatus = FieldUtils.getBindStatus(context, attributeValue); if (bindStatus.isError()) { final StringBuilder strBuilder = new StringBuilder(); final String[] errorMsgs = bindStatus.getErrorMessages(); for (int i = 0; i < errorMsgs.length; i++) { if (i > 0) { strBuilder.append(ERROR_DELIMITER); } final String displayString = ValueFormatterWrapper.getDisplayString(errorMsgs[i], false); strBuilder.append(displayString); } structureHandler.setBody(strBuilder.toString(), false); // Just in case we also have a th:errorclass in this tag structureHandler.setLocalVariable(SpringContextVariableNames.SPRING_FIELD_BIND_STATUS, bindStatus); } else { structureHandler.removeElement(); } }
@Override protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag, final AttributeName attributeName, final String attributeValue, final BindStatus bindStatus, final IElementTagStructureHandler structureHandler) { String name = bindStatus.getExpression(); name = (name == null? "" : name); final String value = tag.getAttributeValue(this.valueAttributeDefinition.getAttributeName()); if (value == null) { throw new TemplateProcessingException( "Attribute \"value\" is required in \"option\" tags"); } final boolean selected = SelectedValueComparatorWrapper.isSelected(bindStatus, HtmlEscape.unescapeHtml(value)); StandardProcessorUtils.setAttribute( structureHandler, this.valueAttributeDefinition, VALUE_ATTR_NAME, RequestDataValueProcessorUtils.processFormFieldValue(context, name, value, "option")); if (selected) { StandardProcessorUtils.setAttribute(structureHandler, this.selectedAttributeDefinition, SELECTED_ATTR_NAME, SELECTED_ATTR_NAME); } else { structureHandler.removeAttribute(this.selectedAttributeDefinition.getAttributeName()); } }
@Test public void bindTagWithoutErrors() throws JspException { PageContext pc = createPageContext(); Errors errors = new ServletRequestDataBinder(new TestBean(), "tb").getBindingResult(); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors); BindTag tag = new BindTag(); tag.setPageContext(pc); tag.setPath("tb"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", status.getExpression() == null); assertTrue("Correct value", status.getValue() == null); assertTrue("Correct displayValue", "".equals(status.getDisplayValue())); assertTrue("Correct isError", !status.isError()); assertTrue("Correct errorCodes", status.getErrorCodes().length == 0); assertTrue("Correct errorMessages", status.getErrorMessages().length == 0); assertTrue("Correct errorCode", "".equals(status.getErrorCode())); assertTrue("Correct errorMessage", "".equals(status.getErrorMessage())); assertTrue("Correct errorMessagesAsString", "".equals(status.getErrorMessagesAsString(","))); }
@Override protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag, final AttributeName attributeName, final String attributeValue, final BindStatus bindStatus, final IElementTagStructureHandler structureHandler) { String name = bindStatus.getExpression(); name = (name == null? "" : name); final String id = computeId(context, tag, name, false); // Thanks to precedence, this should have already been computed final String type = tag.getAttributeValue(this.typeAttributeDefinition.getAttributeName()); // Apply the conversions (editor), depending on type (no conversion for "number" and "range" // Also, no escaping needed as attribute values are always escaped by default final String value = applyConversion(type)? ValueFormatterWrapper.getDisplayString(bindStatus.getValue(), bindStatus.getEditor(), true) : ValueFormatterWrapper.getDisplayString(bindStatus.getActualValue(), true); StandardProcessorUtils.setAttribute(structureHandler, this.idAttributeDefinition, ID_ATTR_NAME, id); // No need to escape: this comes from an existing 'id' or from a token StandardProcessorUtils.setAttribute(structureHandler, this.nameAttributeDefinition, NAME_ATTR_NAME, name); // No need to escape: this is a java-valid token StandardProcessorUtils.setAttribute( structureHandler, this.valueAttributeDefinition, VALUE_ATTR_NAME, RequestDataValueProcessorUtils.processFormFieldValue(context, name, value, type)); }
BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", status.getExpression() == null); assertTrue("Correct value", status.getValue() == null); assertTrue("Correct displayValue", "".equals(status.getDisplayValue())); assertTrue("Correct isError", status.isError()); assertTrue("Correct errorMessages", status.getErrorMessages().length == 1); assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage())); assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(","))); status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", "*".equals(status.getExpression())); assertTrue("Correct value", status.getValue() == null); assertTrue("Correct displayValue", "".equals(status.getDisplayValue())); assertTrue("Correct isError", status.isError()); assertTrue("Correct errorMessages", status.getErrorMessages().length == 1); assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessage())); assertTrue("Correct errorMessagesAsString", "message1".equals(status.getErrorMessagesAsString(",")));
private static boolean checkErrors( final IExpressionContext context, final String expression) { final BindStatus bindStatus = FieldUtils.getBindStatus(context, expression); if (bindStatus == null) { throw new TemplateProcessingException( "Could not bind form errors using expression \"" + expression + "\". Please check this " + "expression is being executed inside the adequate context (e.g. a <form> with a th:object " + "attribute)"); } return bindStatus.isError(); }
@Test public void bindTagWithMappedProperties() throws JspException { PageContext pc = createPageContext(); IndexedTestBean tb = new IndexedTestBean(); Errors errors = new ServletRequestDataBinder(tb, "tb").getBindingResult(); errors.rejectValue("map[key1]", "code1", "message1"); errors.rejectValue("map[key1]", "code2", "message2"); pc.getRequest().setAttribute(BindingResult.MODEL_KEY_PREFIX + "tb", errors); BindTag tag = new BindTag(); tag.setPageContext(pc); tag.setPath("tb.map[key1]"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", "map[key1]".equals(status.getExpression())); assertTrue("Value is TestBean", status.getValue() instanceof TestBean); assertTrue("Correct value", "name4".equals(((TestBean) status.getValue()).getName())); assertTrue("Correct isError", status.isError()); assertTrue("Correct errorCodes", status.getErrorCodes().length == 2); assertTrue("Correct errorMessages", status.getErrorMessages().length == 2); assertTrue("Correct errorCode", "code1".equals(status.getErrorCodes()[0])); assertTrue("Correct errorCode", "code2".equals(status.getErrorCodes()[1])); assertTrue("Correct errorMessage", "message1".equals(status.getErrorMessages()[0])); assertTrue("Correct errorMessage", "message2".equals(status.getErrorMessages()[1])); }
BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", status.getExpression() == null); assertTrue("Correct value", status.getValue() == null); assertTrue("Correct displayValue", "".equals(status.getDisplayValue())); assertTrue("Correct isError", status.isError()); assertTrue("Correct errorCodes", status.getErrorCodes().length == 1); assertTrue("Correct errorCode", "code1".equals(status.getErrorCode())); status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertTrue("Has status variable", status != null); assertTrue("Correct expression", "*".equals(status.getExpression())); assertTrue("Correct value", status.getValue() == null); assertTrue("Correct displayValue", "".equals(status.getDisplayValue())); assertTrue("Correct isError", status.isError()); assertTrue("Correct errorCodes", status.getErrorCodes().length == 1); assertTrue("Correct errorCode", "code1".equals(status.getErrorCode()));
@Override protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag, final AttributeName attributeName, final String attributeValue, final BindStatus bindStatus, final IElementTagStructureHandler structureHandler) { String name = bindStatus.getExpression(); name = (name == null? "" : name); final String id = computeId(context, tag, name, false); final String value = ValueFormatterWrapper.getDisplayString(bindStatus.getValue(), bindStatus.getEditor(), true); String processedValue = RequestDataValueProcessorUtils.processFormFieldValue(context, name, value, "textarea"); if (!StringUtils.isEmpty(processedValue)) { final char c0 = processedValue.charAt(0); if (c0 == '\n') { processedValue = '\n' + processedValue; } else if (c0 == '\r' && processedValue.length() > 1 && processedValue.charAt(1) == '\n') { processedValue = "\r\n" + processedValue; } else if (c0 == '\r') { processedValue = '\r' + processedValue; } } StandardProcessorUtils.setAttribute(structureHandler, this.idAttributeDefinition, ID_ATTR_NAME, id); // No need to escape: this comes from an existing 'id' or from a token StandardProcessorUtils.setAttribute(structureHandler, this.nameAttributeDefinition, NAME_ATTR_NAME, name); // No need to escape: this is a java-valid token structureHandler.setBody((processedValue == null? "" : processedValue), false); }
final Errors errors = bindStatus.getErrors(); if (errors == null) { return Collections.EMPTY_LIST; final String bindExpression = bindStatus.getExpression(); final List<FieldError> fieldErrors = errors.getFieldErrors(bindStatus.getExpression()); for (final FieldError fieldError : fieldErrors) { final String message = requestContext.getMessage(fieldError, false);
@Test public void bindTagWithToStringAndHtmlEscaping() throws JspException { PageContext pc = createPageContext(); BindTag tag = new BindTag(); tag.setPageContext(pc); tag.setPath("tb.doctor"); tag.setHtmlEscape(true); TestBean tb = new TestBean("somebody", 99); NestedTestBean ntb = new NestedTestBean("juergen&eva"); tb.setDoctor(ntb); pc.getRequest().setAttribute("tb", tb); tag.doStartTag(); BindStatus status = (BindStatus) pc.getAttribute(BindTag.STATUS_VARIABLE_NAME, PageContext.REQUEST_SCOPE); assertEquals("doctor", status.getExpression()); assertTrue(status.getValue() instanceof NestedTestBean); assertTrue(status.getDisplayValue().contains("juergen&eva")); }
private boolean isSelected(Object resolvedValue) { BindStatus bindStatus = getBindStatus(); return bindStatus == null || bindStatus.getValue() == null || bindStatus.getActualValue() == null; }
if (bindStatus.isError()) { EntityForm form = (EntityForm) ((BindingResult) bindStatus.getErrors()).getTarget(); for (FieldError err : bindStatus.getErrors().getFieldErrors()) { for (ObjectError err : bindStatus.getErrors().getGlobalErrors()) { Map<String, List<String>> tabErrors = result.get(GENERAL_ERRORS_TAB_KEY); if (tabErrors == null) {
/** * Create a BindStatus for the given bind object, using the "defaultHtmlEscape" setting. * @param path the bean and property path for which values and errors will be resolved (e.g. "person.age") * @param htmlEscape create a BindStatus with automatic HTML escaping? * @return the new BindStatus instance * @throws IllegalStateException if no corresponding Errors object found */ public BindStatus getBindStatus(String path, boolean htmlEscape) throws IllegalStateException { return new BindStatus(this, path, htmlEscape); }
/** * Get the bound value. * @see #getBindStatus() */ @Nullable protected final Object getBoundValue() throws JspException { return getBindStatus().getValue(); }
/** * Get the {@link PropertyEditor}, if any, in use for value bound to this tag. */ @Nullable protected PropertyEditor getPropertyEditor() throws JspException { return getBindStatus().getEditor(); }