docs: @RequestMapping(method = RequestMethod.POST, params = "action=changeColumns")
      public ModelAndView changeColumns(
              HttpServletRequest request,
              HttpServletResponse response,
              @RequestParam("tabId") String tabId,
              @RequestParam("widths[]") String[] widths,
              @RequestParam(value = "deleted[]", required = false) String[] deleted,
              @RequestParam(value = "acceptor", required = false) String acceptor)
              throws IOException, PortalException {
  
          final IUserInstance ui = userInstanceManager.getUserInstance(request);
          final IPerson person = getPerson(ui, response);
  
          final UserPreferencesManager upm = (UserPreferencesManager) ui.getPreferencesManager();
          final IUserLayoutManager ulm = upm.getUserLayoutManager();
  
          final int newColumnCount = widths.length;
  
          // build a list of the current columns for this tab
          final Enumeration<String> columns = ulm.getChildIds(tabId);
          final List<String> columnList = new ArrayList<>();
          while (columns.hasMoreElements()) {
              columnList.add(columns.nextElement());
          }
          final int oldColumnCount = columnList.size();
  
          final Map<String, Object> model = new HashMap<>();
  
          // if the new layout has more columns
          if (newColumnCount > oldColumnCount) {
              final List<String> newColumnIds = new ArrayList<>();
              for (int i = columnList.size(); i < newColumnCount; i++) {
  
                  // create new column element
                  final IUserLayoutFolderDescription newColumn = new UserLayoutFolderDescription();
                  newColumn.setName("Column");
                  newColumn.setId("tbd");
                  newColumn.setFolderType(IUserLayoutFolderDescription.REGULAR_TYPE);
                  newColumn.setHidden(false);
                  newColumn.setUnremovable(false);
                  newColumn.setImmutable(false);
  
                  // add the column to our layout
                  final IUserLayoutNodeDescription node = ulm.addNode(newColumn, tabId, null);
                  newColumnIds.add(node.getId());
  
                  model.put("newColumnIds", newColumnIds);
                  columnList.add(node.getId());
              }
  
          }
  
          // if the new layout has fewer columns
          else if (deleted != null && deleted.length > 0) {
  
              for (String columnId : deleted) {
  
                  // move all channels in the current column to the last valid column
                  final Enumeration channels = ulm.getChildIds(columnId);
                  while (channels.hasMoreElements()) {
                      ulm.addNode(ulm.getNode((String) channels.nextElement()), acceptor, null);
                  }
  
                  // delete the column from the user's layout
                  ulm.deleteNode(columnId);
  
                  columnList.remove(columnId);
              }
          }
  
          /*
           * Now that the number of columns is established, the appearance and behavior of the columns
           * on the page is determined by Structure Stylesheet User Preferences.  "Classic" uPortal
           * columns use a 'width' attribute, while the new(er) columns based on CSS Flex use a
           * 'flexColumns' attribute.
           */
          resetColumnStylesheetUserPreferences(
                  request, person, ulm, columnList); // Clear previous selections
  
          // Choose a column layout strategy...
          boolean useFlexStrategy = false; // default is "classic"
          if (columnList.size() == 1) {
              int firstColumnWidthAsInt = Integer.parseInt(widths[0]);
              if (firstColumnWidthAsInt > 100) {
                  // A single column with a width parameter creater than 100(%)
                  // signals that we want the flexColumns strategy.
                  useFlexStrategy = true;
              }
          }
  
          // Update Structure Stylesheet User Preferences based on the selected strategy
          if (useFlexStrategy) {
              updateColumnStylesheetUserPreferencesFlex(request, person, ulm, columnList, widths);
          } else {
              updateColumnStylesheetUserPreferencesClassic(request, person, ulm, columnList, widths);
          }
  
          try {
              ulm.saveUserLayout();
          } catch (PortalException e) {
              logger.warn("Error saving layout", e);
          }
  
          return new ModelAndView("jsonView", model);
      }