code: @Override
      protected void extractSubTree(List<JoinNode> leafNodes) {
          JoinNode[] children = {m_leftNode, m_rightNode};
          for (JoinNode child : children) {
  
              // Leaf nodes don't have a significant join type,
              // test for them first and never attempt to start a new tree at a leaf.
              if ( ! (child instanceof BranchNode)) {
                  continue;
              }
  
              if (((BranchNode)child).m_joinType == m_joinType) {
                  // The join type for this node is the same as the root's one
                  // Keep walking down the tree
                  child.extractSubTree(leafNodes);
              } else {
                  // The join type for this join differs from the root's one
                  // Terminate the sub-tree
                  leafNodes.add(child);
                  // Replace the join node with the temporary node having the id negated
                  JoinNode tempNode = new TableLeafNode(
                          -child.m_id, child.m_joinExpr, child.m_whereExpr, null);
                  if (child == m_leftNode) {
                      m_leftNode = tempNode;
                  } else {
                      m_rightNode = tempNode;
                  }
              }
          }
      }
docs: Starting from the root recurse to its children stopping at the first join node
  of the different type and discontinue the tree at this point by replacing the join node with
  the temporary node which id matches the join node id. This join node is the root of the next
  sub-tree.
  @param root - The root of the join tree
  @param leafNodes - the list of the root nodes of the next sub-trees