code: private void mapSubstitutes(RGroupList rgpList, int listOffset, Integer[] distribution, RGroup[] mapping,
              List<List<RGroup>> result) {
          if (listOffset == distribution.length) {
              List<RGroup> mapped = new ArrayList<RGroup>();
              for (RGroup rgrp : mapping)
                  mapped.add(rgrp);
              result.add(mapped);
          } else {
              if (distribution[listOffset] == 0) {
                  mapping[listOffset] = null;
                  mapSubstitutes(rgpList, listOffset + 1, distribution, mapping, result);
              } else {
                  for (RGroup rgrp : rgpList.getRGroups()) {
                      mapping[listOffset] = rgrp;
                      mapSubstitutes(rgpList, listOffset + 1, distribution, mapping, result);
                  }
              }
          }
      }
docs: Maps the distribution of an R-group to all possible substitute combinations.
  This is best illustrated by an example.<br>
  Say R2 occurs twice in the root, and has condition >0. So a valid
  output configuration can have either one or two substitutes.
  The distributions will have been calculated to be the following
  solutions: [0,1], [1,0], [1,1]   <br>
  To start with [1,1], assume two possible substitutes have been
  defined for R2, namely *C=O and *C-N. Then the distribution [1,1]
  should lead to four mappings:   <br>
  [*C=O,*C=O], [*C-N,*C-N], [*C=O,*C-N], [*C-N,*C=O].    <br>
  These mappings are generated in this function, as well as the other valid mappings
  for [0,1] and [1,0]: <br>
  [*C=O,null], [*C-N,null], [null,*C=O], [null,*C-N].   <br>
  So the example would have this function produce eight mappings (result list size==8).
  
  @param rgpList
  @param listOffset
  @param distribution
  @param mapping
  @param result