@Test
 public void testCleanModel() {
   ExtendedModelMap model = new ExtendedModelMap().addAttribute("modelMap", "test");
   JsonUtils.cleanModel(model);
   Assert.assertThat(model.asMap().containsKey("modelMap"), is(false));
   Assert.assertThat(model.asMap().containsKey(SpringSprout2System.CLEAN_KEY), is(true));
 }
  private WebDataBinder resolveModelAttribute(
      String attrName,
      MethodParameter methodParam,
      ExtendedModelMap implicitModel,
      NativeWebRequest webRequest,
      Object handler)
      throws Exception {

    // Bind request parameter onto object...
    String name = attrName;
    if ("".equals(name)) {
      name = Conventions.getVariableNameForParameter(methodParam);
    }
    Class<?> paramType = methodParam.getParameterType();
    Object bindObject;
    if (implicitModel.containsKey(name)) {
      bindObject = implicitModel.get(name);
    } else if (this.methodResolver.isSessionAttribute(name, paramType)) {
      bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
      if (bindObject == null) {
        raiseSessionRequiredException(
            "Session attribute '" + name + "' required - not found in session");
      }
    } else {
      bindObject = BeanUtils.instantiateClass(paramType);
    }
    WebDataBinder binder = createBinder(webRequest, bindObject, name);
    initBinder(handler, name, binder, webRequest);
    return binder;
  }
  public final Object invokeHandlerMethod(
      Method handlerMethod,
      Object handler,
      NativeWebRequest webRequest,
      ExtendedModelMap implicitModel)
      throws Exception {

    Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
    try {
      boolean debug = logger.isDebugEnabled();
      for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
        Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
        if (attrValue != null) {
          implicitModel.addAttribute(attrName, attrValue);
        }
      }
      for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
        Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
        Object[] args =
            resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
        if (debug) {
          logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
        }
        String attrName =
            AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
        if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
          continue;
        }
        ReflectionUtils.makeAccessible(attributeMethodToInvoke);
        Object attrValue = attributeMethodToInvoke.invoke(handler, args);
        if ("".equals(attrName)) {
          Class<?> resolvedType =
              GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
          attrName =
              Conventions.getVariableNameForReturnType(
                  attributeMethodToInvoke, resolvedType, attrValue);
        }
        if (!implicitModel.containsAttribute(attrName)) {
          implicitModel.addAttribute(attrName, attrValue);
        }
      }
      Object[] args =
          resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
      if (debug) {
        logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
      }
      ReflectionUtils.makeAccessible(handlerMethodToInvoke);
      return handlerMethodToInvoke.invoke(handler, args);
    } catch (IllegalStateException ex) {
      // Internal assertion failed (e.g. invalid signature):
      // throw exception with full handler method context...
      throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
    } catch (InvocationTargetException ex) {
      // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
      ReflectionUtils.rethrowException(ex.getTargetException());
      return null;
    }
  }
 @Test
 public void testTotal() throws Exception {
   final ExtendedModelMap model = new ExtendedModelMap();
   miniCartComponentModel.setTotalDisplay(CartTotalDisplayType.TOTAL);
   given(cmsComponentService.getAbstractCMSComponent(TEST_COMPONENT_UID))
       .willReturn(miniCartComponentModel);
   miniCartComponentController.handleGet(request, response, model);
   final PriceData priceData = (PriceData) model.get(MiniCartComponentController.TOTAL_PRICE);
   Assert.assertEquals(TOTAL_VALUE, priceData.getValue());
 }
 @Test
 public void testTotalWithoutDelivery() throws Exception {
   final ExtendedModelMap model = new ExtendedModelMap();
   miniCartComponentModel.setTotalDisplay(CartTotalDisplayType.TOTAL_WITHOUT_DELIVERY);
   given(cmsComponentService.getSimpleCMSComponent(TEST_COMPONENT_UID))
       .willReturn(miniCartComponentModel);
   miniCartComponentController.handleGet(request, response, model);
   final PriceData priceData =
       (PriceData) model.get(MiniCartComponentController.TOTAL_NO_DELIVERY);
   Assert.assertEquals(TOTAL_VALUE.subtract(DELIVERY_VALUE), priceData.getValue());
 }
  public final Object invokeHandlerMethod(
      Method handlerMethod,
      Object handler,
      NativeWebRequest webRequest,
      ExtendedModelMap implicitModel)
      throws Exception {

    Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
    try {
      boolean debug = logger.isDebugEnabled();
      for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
        Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
        if (attrValue != null) {
          implicitModel.addAttribute(attrName, attrValue);
        }
      }
      for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
        Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
        Object[] args =
            resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
        if (debug) {
          logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
        }
        String attrName =
            AnnotationUtils.findAnnotation(attributeMethodToInvoke, ModelAttribute.class).value();
        if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
          continue;
        }
        Object attrValue = doInvokeMethod(attributeMethodToInvoke, handler, args);
        if ("".equals(attrName)) {
          Class resolvedType =
              GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
          attrName =
              Conventions.getVariableNameForReturnType(
                  attributeMethodToInvoke, resolvedType, attrValue);
        }
        if (!implicitModel.containsAttribute(attrName)) {
          implicitModel.addAttribute(attrName, attrValue);
        }
      }
      Object[] args =
          resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
      if (debug) {
        logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
      }
      return doInvokeMethod(handlerMethodToInvoke, handler, args);
    } catch (IllegalStateException ex) {
      // Throw exception with full handler method context...
      throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
    }
  }
  public final void updateModelAttributes(
      Object handler,
      Map<String, Object> mavModel,
      ExtendedModelMap implicitModel,
      NativeWebRequest webRequest)
      throws Exception {

    if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
      for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
        this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
      }
    }

    // Expose model attributes as session attributes, if required.
    // Expose BindingResults for all attributes, making custom editors available.
    Map<String, Object> model = (mavModel != null ? mavModel : implicitModel);
    if (model != null) {
      try {
        String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
        for (String attrName : originalAttrNames) {
          Object attrValue = model.get(attrName);
          boolean isSessionAttr =
              this.methodResolver.isSessionAttribute(
                  attrName, (attrValue != null ? attrValue.getClass() : null));
          if (isSessionAttr) {
            if (this.sessionStatus.isComplete()) {
              implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
            } else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
              this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
            }
          }
          if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX)
              && (isSessionAttr || isBindingCandidate(attrValue))) {
            String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
            if (mavModel != null && !model.containsKey(bindingResultKey)) {
              WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
              initBinder(handler, attrName, binder, webRequest);
              mavModel.put(bindingResultKey, binder.getBindingResult());
            }
          }
        }
      } catch (InvocationTargetException ex) {
        // User-defined @InitBinder method threw an exception...
        ReflectionUtils.rethrowException(ex.getTargetException());
      }
    }
  }
 @RequestMapping("EDIT")
 public String myOtherHandle(
     TB tb, BindingResult errors, ExtendedModelMap model, MySpecialArg arg) {
   TestBean tbReal = (TestBean) tb;
   tbReal.setName("myName");
   assertTrue(model.get("ITestBean") instanceof DerivedTestBean);
   assertNotNull(arg);
   return super.myHandle(tbReal, errors, model);
 }
  protected final void addReturnValueAsModelAttribute(
      Method handlerMethod, Class handlerType, Object returnValue, ExtendedModelMap implicitModel) {

    ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
    String attrName = (attr != null ? attr.value() : "");
    if ("".equals(attrName)) {
      Class resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
      attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
    }
    implicitModel.addAttribute(attrName, returnValue);
  }
  @SuppressWarnings("unchecked")
  private Object[] resolveHandlerArguments(
      Method handlerMethod,
      Object handler,
      NativeWebRequest webRequest,
      ExtendedModelMap implicitModel)
      throws Exception {

    Class[] paramTypes = handlerMethod.getParameterTypes();
    Object[] args = new Object[paramTypes.length];

    for (int i = 0; i < args.length; i++) {
      MethodParameter methodParam = new MethodParameter(handlerMethod, i);
      methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
      GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
      String paramName = null;
      String headerName = null;
      boolean requestBodyFound = false;
      String cookieName = null;
      String pathVarName = null;
      String attrName = null;
      boolean required = false;
      String defaultValue = null;
      boolean validate = false;
      int found = 0;
      Annotation[] paramAnns = methodParam.getParameterAnnotations();

      for (Annotation paramAnn : paramAnns) {
        if (RequestParam.class.isInstance(paramAnn)) {
          RequestParam requestParam = (RequestParam) paramAnn;
          paramName = requestParam.value();
          required = requestParam.required();
          defaultValue = requestParam.defaultValue();
          found++;
        } else if (RequestHeader.class.isInstance(paramAnn)) {
          RequestHeader requestHeader = (RequestHeader) paramAnn;
          headerName = requestHeader.value();
          required = requestHeader.required();
          defaultValue = requestHeader.defaultValue();
          found++;
        } else if (RequestBody.class.isInstance(paramAnn)) {
          requestBodyFound = true;
          found++;
        } else if (CookieValue.class.isInstance(paramAnn)) {
          CookieValue cookieValue = (CookieValue) paramAnn;
          cookieName = cookieValue.value();
          required = cookieValue.required();
          defaultValue = cookieValue.defaultValue();
          found++;
        } else if (PathVariable.class.isInstance(paramAnn)) {
          PathVariable pathVar = (PathVariable) paramAnn;
          pathVarName = pathVar.value();
          found++;
        } else if (ModelAttribute.class.isInstance(paramAnn)) {
          ModelAttribute attr = (ModelAttribute) paramAnn;
          attrName = attr.value();
          found++;
        } else if (Value.class.isInstance(paramAnn)) {
          defaultValue = ((Value) paramAnn).value();
        } else if ("Valid".equals(paramAnn.annotationType().getSimpleName())) {
          validate = true;
        }
      }

      if (found > 1) {
        throw new IllegalStateException(
            "Handler parameter annotations are exclusive choices - "
                + "do not specify more than one such annotation on the same parameter: "
                + handlerMethod);
      }

      if (found == 0) {
        Object argValue = resolveCommonArgument(methodParam, webRequest);
        if (argValue != WebArgumentResolver.UNRESOLVED) {
          args[i] = argValue;
        } else if (defaultValue != null) {
          args[i] = resolveDefaultValue(defaultValue);
        } else {
          Class paramType = methodParam.getParameterType();
          if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
            args[i] = implicitModel;
          } else if (SessionStatus.class.isAssignableFrom(paramType)) {
            args[i] = this.sessionStatus;
          } else if (Errors.class.isAssignableFrom(paramType)) {
            throw new IllegalStateException(
                "Errors/BindingResult argument declared "
                    + "without preceding model attribute. Check your handler method signature!");
          } else if (BeanUtils.isSimpleProperty(paramType)) {
            paramName = "";
          } else {
            attrName = "";
          }
        }
      }

      if (paramName != null) {
        args[i] =
            resolveRequestParam(
                paramName, required, defaultValue, methodParam, webRequest, handler);
      } else if (headerName != null) {
        args[i] =
            resolveRequestHeader(
                headerName, required, defaultValue, methodParam, webRequest, handler);
      } else if (requestBodyFound) {
        args[i] = resolveRequestBody(methodParam, webRequest, handler);
      } else if (cookieName != null) {
        args[i] =
            resolveCookieValue(
                cookieName, required, defaultValue, methodParam, webRequest, handler);
      } else if (pathVarName != null) {
        args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
      } else if (attrName != null) {
        WebDataBinder binder =
            resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
        boolean assignBindingResult =
            (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
        if (binder.getTarget() != null) {
          doBind(binder, webRequest, validate, !assignBindingResult);
        }
        args[i] = binder.getTarget();
        if (assignBindingResult) {
          args[i + 1] = binder.getBindingResult();
          i++;
        }
        implicitModel.putAll(binder.getBindingResult().getModel());
      }
    }

    return args;
  }