// this method assume jbbNodeSet contains nodes from the same JBB
EstLogPropSharedPtr AppliedStatMan::getStatsForCANodeIdSet(
					const CANodeIdSet & jbbNodeSet)
{

  EstLogPropSharedPtr outputEstLogProp;
  CANodeIdSet combinedNodeSet = jbbNodeSet;
  combinedNodeSet += *(jbbNodeSet.getJBBInput()->getNodeSet());
  EstLogPropSharedPtr jBBInput = jbbNodeSet.getJBBInput();
  if ((outputEstLogProp = getCachedStatistics(&combinedNodeSet)) == NULL)
    outputEstLogProp = synthesizeLogProp(&jbbNodeSet, jBBInput);

  return outputEstLogProp;
}
EstLogPropSharedPtr AppliedStatMan::joinJBBChildren(
					const CANodeIdSet & leftChildren,
					const CANodeIdSet & rightChildren,
					EstLogPropSharedPtr & inLP)
{

  EstLogPropSharedPtr inputLP = inLP;

  EstLogPropSharedPtr outputEstLogProp;

  if(inputLP == (*GLOBAL_EMPTY_INPUT_LOGPROP))
    inputLP = leftChildren.getJBBInput();

  // Because there exist a nodeSet for the left, right and the outer
  // child, hence these properties are cacheable. Check to see if the
  // outputEstLogProp of the join for the given inLP exist in the cache

  CANodeIdSet combinedNodeSet = leftChildren;
  combinedNodeSet.insert(rightChildren);

  CANodeIdSet * inNodeSet = NULL;

  if (inputLP->isCacheable())
  {
    inNodeSet = inputLP->getNodeSet();

    CANodeIdSet combinedWithInputNodeSet = combinedNodeSet;
    combinedWithInputNodeSet.insert(*inNodeSet);

    outputEstLogProp = getCachedStatistics(&combinedWithInputNodeSet);
  }

  if(outputEstLogProp == NULL)
    outputEstLogProp = synthesizeLogProp(&combinedNodeSet, inputLP);
  
  return outputEstLogProp;
} // AppliedStatMan::joinJBBChildren