@Override
  protected Map<String, Object> referenceData(
      HttpServletRequest request, Object command, Errors errors, int page) throws Exception {
    UserSessionData usd = getUserSessionData(request);
    Map<String, Object> referenceData = new HashMap<String, Object>();
    int currentPage = getCurrentPage(request);

    log.debug("referenceData: Current page in refData " + currentPage);

    referenceData.put("dirtyFlag", usd.isDirty() ? "true" : "false");
    referenceData.put("ImageUrlBuilder", urlBuilder);
    referenceData.put("allSizes", imageSizeDefMgr.getAllImageSizes());
    referenceData.put("page", currentPage);

    MasterImageMetaData mimd = usd.getMimd();

    if (usd.getPages() == null) {
      log.debug("referenceData: no pages defined yet");
      setPagesDynamically(request, null);
    }
    int pageCount = usd.getPages().length;
    log.debug("Page count is " + pageCount);
    referenceData.put("pagecount", pageCount);

    if (currentPage == 0) {
      String sizedDivStyle = "none";
      if (StringUtils.isNotBlank(mimd.getImageKey())) {
        sizedDivStyle = "block";
      }
      referenceData.put("sizedDivStyle", sizedDivStyle);
      referenceData.put("allDisplaySizes", buildAllSizesList(mimd));
      referenceData.put("metadata", buildMasterImageDisplay(mimd));
    }

    if (currentPage > 0 && currentPage < getPageCount(request, command) - 1) {
      SizedImageMetaData simd = getCurrentSizedImage(mimd, currentPage - 1);
      referenceData.put("SizedImage", simd);
      Map<String, String> cropbox = buildCropBox(simd);
      referenceData.put("cropbox", cropbox);
      ImageSizeDefinition isd = simd.getSizeDefinition();
      referenceData.put("sizecode", isd.getCode());
      referenceData.put("sizelabel", isd.getLabel());
      referenceData.put("definedHeight", isd.getHeight());
      referenceData.put("definedWidth", isd.getWidth());

      Map<String, String> displayImage = buildDisplayImage(usd);
      referenceData.put("displayImage", displayImage);

    } else if (currentPage == getPageCount(request, command) - 1) { // this is the confirm page.

      Map<String, String> displayImage = buildDisplayImage(usd);
      referenceData.put("displayImage", displayImage);
      List<Map<String, String>> sizedImagesDisplay =
          buildAllSizedImagesDisplay(mimd.getSizedImages());
      referenceData.put("sizedImages", sizedImagesDisplay);
    }

    return referenceData;
  }
  protected Map<String, String> buildCropBox(SizedImageMetaData simd) {
    Map<String, String> box = new HashMap<String, String>();
    ImageSizeDefinition size = simd.getSizeDefinition();
    if (simd.getHeight() > 0 && simd.getWidth() > 0) {
      Rectangle rect = new Rectangle(simd.getX(), simd.getY(), simd.getWidth(), simd.getHeight());

      box.put("height", String.valueOf(Math.round(rect.getHeight())));
      box.put("width", String.valueOf(Math.round(rect.getWidth())));
      box.put("x", String.valueOf(Math.round(rect.getX())));
      box.put("y", String.valueOf(Math.round(rect.getY())));
      box.put("constraint", simd.isConstraint() ? "1" : "0");
    } else {
      box.put("height", String.valueOf(size.getHeight()));
      box.put("width", String.valueOf(size.getWidth()));
      box.put("x", "0");
      box.put("y", "0");
      box.put("constraint", (size.getHeight() > 0 && size.getWidth() > 0) ? "1" : "0");
    }
    return box;
  }
  @Override
  protected void onBind(HttpServletRequest request, Object command, BindException errors)
      throws Exception {
    log.debug("onBind: doing onBind...");
    UserSessionData usd = getUserSessionData(request);
    MasterImageMetaData mimd = usd.getMimd();

    ImageBean ib = (ImageBean) command;

    if (mimd == null) {
      log.error("onBind: mimd attribute is not set in session.");
    } else {
      int currentPage = getCurrentPage(request);

      if (request instanceof MultipartHttpServletRequest) {
        MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
        MultipartFile mpFile = mRequest.getFile(FILE_UPLOAD_FIELD);

        String action = request.getParameter("action");
        log.debug("onBind: the action is: " + action);

        if (mpFile.isEmpty() && StringUtils.isBlank(action)) {
          log.debug("onBind: nothing has been uploaded - not storing image...");
        } else if (mpFile.isEmpty() && action.equals("cleared")) {
          log.debug(
              "onBind: nothing has been uploaded and something has been cleared - clearing stored image if any...");
          mimd.setImageKey(null);
          mimd.setMetaData(null);
          mimd.clearSizedImages();
          usd.setDirty(true); // clearing the file always sets dirty.
        } else {
          log.debug(
              "onBind: the original name of the file being uploaded is: "
                  + mpFile.getOriginalFilename());
          storeImage(mimd, mpFile);
          setupDisplayImage(mimd, usd);
          usd.setDirty(true); // uploaded files are always dirty.
        }

        mimd.setAlt(ib.getAlt());
        mimd.setDescription(ib.getDescription());
        mimd.setDisplayTitle(ib.getDisplayTitle());
        mimd.setSysTitle(ib.getSysTitle());
      }
      // set the dirty flag if the form is dirty or the session is already dirty.
      usd.setDirty(usd.isDirty() || ib.isDirty());
      log.debug("onBind: The dirty flag is " + usd.isDirty());

      log.debug(
          "onBind: There are "
              + getPageCount(request, command)
              + " pages. -- currently on page "
              + getCurrentPage(request));

      log.debug("onBind: current Page is " + currentPage);
      // Figure out how many pages you will need to go through
      if (currentPage == 0) {
        String contentId = request.getParameter("sys_contentid");
        String folderId = request.getParameter("sys_folderid");
        String sessionId = RxRequestUtils.getSessionId(request);
        String username = request.getRemoteUser();
        if (StringUtils.isBlank(contentId)
            && StringUtils.isNotBlank(folderId)
            && StringUtils.isNotBlank(ib.getSysTitle())) {
          boolean bval =
              imagePersistenceManager.validateSystemTitleUnique(
                  ib.getSysTitle(), folderId, sessionId, username);
          if (!bval) {
            log.info("system title is not unique in folder " + ib.getSysTitle());
            errors.rejectValue(
                "sysTitle",
                "title.not.unique",
                new String[] {ib.getSysTitle()},
                "System Title is not unique in the specified folder.");
          }
        }

        log.debug("onBind: ib.getSizedImages(): " + ib.getSizedImages());
        setPagesDynamically(request, ib.getSizedImages());
        setupSizedImages(request, ib.getSizedImages(), mimd);
      }

      if (currentPage > 0 && currentPage < getPageCount(request, command) - 1) {
        log.debug("onBind: dealing with binding data for page " + currentPage);

        SizedImageMetaData simd = getCurrentSizedImage(mimd, currentPage - 1);
        ImageSizeDefinition isd = simd.getSizeDefinition();
        if (ib.getX() == 0
            && ib.getY() == 0
            && ib.getWidth() == 0
            && ib.getHeight() == 0) { // ignore this request, it was likely caused by a refresh...
          log.debug("No crop box data present, skipping this request");
          return;
        }
        // can't do this on the client side because MSIE cannot detect change events.
        if (!usd.isDirty()) { // not already dirty, so we must check to see if the box has changed
          if (simd.getX() != ib.getX()
              || simd.getY() != ib.getY()
              || simd.getHeight() != ib.getHeight()
              || simd.getWidth() != ib.getWidth()) {
            usd.setDirty(true);
          }
        }

        Rectangle cropBox = new Rectangle(ib.getX(), ib.getY(), ib.getWidth(), ib.getHeight());
        double scaleFactor = usd.getScaleFactor();
        if (scaleFactor > 1.0) {
          log.debug("scaling crop box " + scaleFactor);
          ImageMetaData imd = mimd.getMetaData();
          cropBox =
              scaledRectangle(cropBox, scaleFactor, new Dimension(imd.getWidth(), imd.getHeight()));
          log.debug("new crop box is " + cropBox);
        }
        Dimension size = new Dimension(isd.getWidth(), isd.getHeight());

        resizeSimpleImage(simd, mimd.getImageKey(), cropBox, size);
        simd.setX(ib.getX());
        simd.setY(ib.getY());
        simd.setHeight(ib.getHeight());
        simd.setWidth(ib.getWidth());

        Boolean constraint = ib.isConstraint();
        log.debug("constraint from ib: " + constraint);
        log.debug("request constraint: " + request.getParameter("constraint"));
        if (constraint == null) simd.setConstraint(false);
        else if (constraint.booleanValue()) simd.setConstraint(constraint);

      } else log.debug("onBind: page is not > 0 or < " + (getPageCount(request, command) - 1));
    }

    log.debug("onBind: END");
  }