private int[] getSelectedRows(int[] selectedRowsNumber, Map[] selectedRowsKeys, Tab tab) {
    if (selectedRowsKeys == null || selectedRowsKeys.length == 0) return new int[0];
    // selectedRowsNumber is the most performant so we use it when possible
    else if (selectedRowsNumber.length == selectedRowsKeys.length) return selectedRowsNumber;
    else {
      // find the rows from the selectedKeys

      // This has a poor performance, but it covers the case when the selected
      // rows are not loaded for the tab, something that can occurs if the user
      // select rows and afterwards reorder the list.
      try {
        int[] s = new int[selectedRowsKeys.length];
        List selectedKeys = Arrays.asList(selectedRowsKeys);
        int end = tab.getTableModel().getTotalSize();
        int x = 0;
        for (int i = 0; i < end; i++) {
          Map key = (Map) tab.getTableModel().getObjectAt(i);
          if (selectedKeys.contains(key)) {
            s[x] = i;
            x++;
          }
        }
        return s;
      } catch (Exception ex) {
        log.warn(XavaResources.getString("fails_selected"), ex);
        throw new XavaException("fails_selected");
      }
    }
  }
 private InputStream getReport(
     HttpServletRequest request,
     HttpServletResponse response,
     Tab tab,
     TableModel tableModel,
     Integer columnCountLimit)
     throws ServletException, IOException {
   StringBuffer suri = new StringBuffer();
   suri.append("/xava/jasperReport");
   suri.append("?language=");
   suri.append(Locales.getCurrent().getLanguage());
   suri.append("&widths=");
   suri.append(Arrays.toString(getWidths(tableModel)));
   if (columnCountLimit != null) {
     suri.append("&columnCountLimit=");
     suri.append(columnCountLimit);
   }
   response.setCharacterEncoding(XSystem.getEncoding());
   return Servlets.getURIAsStream(request, response, suri.toString());
 }