public void valueChanged(ListSelectionEvent e) {
          if (!e.getValueIsAdjusting() && cur == null) { // prevent recursion
            ListSelectionModel lsm = (ListSelectionModel) e.getSource();
            cur = lsm;
            ListSelectionModel rfl; // reflect changes in other model
            int mn = lsm.getMinSelectionIndex();
            int mx = lsm.getMaxSelectionIndex();
            if (lsm == src) {
              rfl = dst;
            } else {
              rfl = src;
            }
            int min = 0;
            int max =
                map == null
                    ? lsm.getMaxSelectionIndex()
                    : lsm == src ? map.getSrcSize() : map.getDstSize();
            BitSet bidx = null;
            if (map != null && !map.isOneToOne()) {
              bidx = new BitSet(max + 1);
            }
            rfl.setValueIsAdjusting(true);
            if (map == null) {
              rfl.clearSelection();
            }

            for (int i = min; i <= max; i++) {
              if (map == null) {
                if (lsm.isSelectedIndex(i)) {
                  rfl.addSelectionInterval(i, i);
                } else {
                  rfl.removeSelectionInterval(i, i);
                }
              } else if (map.isOneToOne()) {
                int j = lsm == src ? map.getDst(i) : map.getSrc(i);
                if (j < 0) continue;
                if (lsm.isSelectedIndex(i)) {
                  rfl.addSelectionInterval(j, j);
                } else {
                  rfl.removeSelectionInterval(j, j);
                }
              } else {
                // How to deal with OneToMany mapping?
                // All dst indices selected -> select src index
                // Any dst indices selected -> select src index
                //
                if (!bidx.get(i)) {
                  bidx.set(i); // Flag this index as visited
                  // Get the set of destination indices
                  int di[] = lsm == src ? map.getDsts(i) : map.getSrcs(i);
                  if (di != null) {
                    for (int j = 0; j < di.length; j++) {
                      if (di[j] < 0) continue;
                      // Get the set of source indices for each destination index
                      int si[] = lsm == dst ? map.getDsts(di[j]) : map.getSrcs(di[j]);
                      if (si != null) {
                        boolean allSet = true;
                        boolean anySet = false;
                        for (int k = 0; k < si.length; k++) {
                          bidx.set(si[k]); // Flag this index as visited
                          allSet &= lsm.isSelectedIndex(si[k]);
                          anySet |= lsm.isSelectedIndex(si[k]);
                        }
                        if (allSet || (!allSelected && anySet)) {
                          rfl.addSelectionInterval(di[j], di[j]);
                        } else {
                          rfl.removeSelectionInterval(di[j], di[j]);
                        }
                      }
                    }
                  }
                }
              }
            }
            rfl.setValueIsAdjusting(false);
            cur = null;
          }
        }