private List getSortColumns(Table table, String sortColumnProvider) {
    List sortColumns = null;

    if (sortColumnProvider != null) {
      sortColumnProvider = sortColumnProvider.trim();

      StringTokenizer sortColumnProviderTokenizer = new StringTokenizer(sortColumnProvider, ",");

      String sortColumnToken;
      while (sortColumnProviderTokenizer.hasMoreTokens()) {
        sortColumnToken = sortColumnProviderTokenizer.nextToken().trim();
        StringTokenizer sortColumnTokenizer = new StringTokenizer(sortColumnToken, " ");

        String sortColumnName = null;
        int sortOrder = SortColumn.ASCENDING;

        if (sortColumnTokenizer.hasMoreTokens()) sortColumnName = sortColumnTokenizer.nextToken();
        if (sortColumnTokenizer.hasMoreTokens()) {
          String sOrder = sortColumnTokenizer.nextToken().toLowerCase();

          if (sOrder.equals("desc")) sortOrder = SortColumn.DESCENDING;
        }

        if (sortColumnName != null) {
          IColumn sortColumn = table.getColumn(sortColumnName);
          if (sortColumn != null) {
            SortColumn sCol = new SortColumn(sortColumn);
            sCol.setSortOrder(sortOrder);

            if (sortColumns == null) sortColumns = new ArrayList();

            sortColumns.add(sCol);
          }
        }
      }
    }

    return sortColumns;
  }
  // lazy load
  private void internal_lazyLoadChilderenIfNeeded(Object obj) {
    if (obj instanceof UserNode) {
      UserNode un = (UserNode) obj;
      if (!un.isInitialized()) {
        un.flagInitialized();

        // check if we have multiple child relations
        RelationInfo[] relationInfos = bindingInfo.getNRelationInfos(un);
        if (relationInfos != null && relationInfos.length > 0) {
          int id = 0;
          for (RelationInfo relationInfo : relationInfos)
            un.add(new RelationNode(id++, relationInfo));
          return;
        }

        IRecord rec = un.getRecord();
        if (rec != null) {
          IFoundSet nfs;
          String n_relationName = bindingInfo.getNRelationName(un);
          String m_relationName = bindingInfo.getMRelationName(un);

          nfs = rec.getRelatedFoundSet(n_relationName);
          if (nfs != null && nfs.getSize() > 0) {
            if (m_relationName == null) {
              List sortColumns =
                  getSortColumns(
                      (Table) ((IFoundSetInternal) nfs).getTable(),
                      bindingInfo.getChildSortDataprovider(un));
              if (sortColumns != null) {
                try {
                  nfs.sort(sortColumns);
                } catch (Exception ex) {
                  Debug.error(ex);
                }
              }
              for (int i = 0; i < nfs.getSize(); i++) {
                nfs.getRecord(i); // to force next record loading
                createChildNode(un, nfs, i);
              }
            } else {
              ArrayList mfsRecordsSortedIdx = new ArrayList();
              ArrayList mfsSorted = new ArrayList();

              int sortOrder = SortColumn.ASCENDING;

              for (int ii = 0; ii < nfs.getSize(); ii++) {
                IRecord rel = nfs.getRecord(ii);
                IFoundSet mfs = rel.getRelatedFoundSet(m_relationName);
                if (mfs != null) {
                  for (int i = 0; i < mfs.getSize(); i++) {
                    IRecord mfsRec = mfs.getRecord(i);

                    // if sorting add mfs value o right position
                    List sortColumns =
                        getSortColumns(
                            (Table) ((IFoundSetInternal) mfs).getTable(),
                            bindingInfo.getChildSortDataprovider(un));
                    if (sortColumns != null) {
                      SortColumn sortCol = (SortColumn) sortColumns.get(0);
                      String sortDataProvider = sortCol.getDataProviderID();
                      sortOrder = sortCol.getSortOrder();
                      if (mfsRec != null) {
                        if (mfsRec.getValue(sortDataProvider) != null
                            && mfsRec.getValue(sortDataProvider) instanceof Comparable) {
                          Comparable sMfsRecValue = (Comparable) mfsRec.getValue(sortDataProvider);
                          Comparable sSortedValue;
                          int n;
                          for (n = 0; n < mfsRecordsSortedIdx.size(); n++) {
                            int nSortedRecIdx = ((Integer) mfsRecordsSortedIdx.get(n)).intValue();
                            sSortedValue =
                                (Comparable)
                                    ((IFoundSet) mfsSorted.get(n))
                                        .getRecord(nSortedRecIdx)
                                        .getValue(sortDataProvider);

                            if (sSortedValue == null) continue;

                            if (sMfsRecValue
                                    .getClass()
                                    .getName()
                                    .equals(sSortedValue.getClass().getName())
                                && sMfsRecValue.compareTo(sSortedValue) < 0) {
                              break;
                            }
                          }

                          mfsRecordsSortedIdx.add(n, new Integer(i));
                          mfsSorted.add(n, mfs);
                        } else {
                          mfsRecordsSortedIdx.add(0, new Integer(i));
                          mfsSorted.add(0, mfs);
                        }
                      }
                    } else {
                      mfsRecordsSortedIdx.add(new Integer(i));
                      mfsSorted.add(mfs);
                    }
                  }
                }
              }

              // should be done better
              if (sortOrder == SortColumn.ASCENDING) {
                for (int i = 0; i < mfsRecordsSortedIdx.size(); i++) {
                  createChildNode(
                      (DefaultMutableTreeNode) un,
                      (IFoundSet) mfsSorted.get(i),
                      ((Integer) mfsRecordsSortedIdx.get(i)).intValue());
                }
              } else {
                for (int i = mfsRecordsSortedIdx.size() - 1; i >= 0; i--) {
                  createChildNode(
                      (DefaultMutableTreeNode) un,
                      (IFoundSet) mfsSorted.get(i),
                      ((Integer) mfsRecordsSortedIdx.get(i)).intValue());
                }
              }
            }
          }
        }
      }
    } else if (obj instanceof RelationNode) {
      RelationNode un = (RelationNode) obj;
      if (!un.isInitialized()) {
        un.flagInitialized();

        UserNode parentUserNode = (UserNode) un.getParent();
        IRecord parentRecord = parentUserNode.getRecord();

        IFoundSet nfs =
            parentRecord.getRelatedFoundSet(((RelationInfo) un.getUserObject()).getNRelationName());

        if (nfs != null && nfs.getSize() > 0) {
          for (int i = 0; i < nfs.getSize(); i++) {
            createChildNode(un, nfs, i);
            nfs.getRecord(i);
          }
        }
      }
    }
  }