Program: 176968
Project: 176968
Buggy source:
/** 
 * Pushes <code>node</code> and its descendants recursively to flush stack  residing into persistence cache
 * @param pc
 * @param node
 */
public void addNodesToFlushStack(PersistenceCache pc,Node node){
  FlushStack flushStack=pc.getFlushStack();
  MainCache mainCache=(MainCache)pc.getMainCache();
  Map<NodeLink,Node> children=node.getChildren();
  if (children != null) {
    Map<NodeLink,Node> oneToOneChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> oneToManyChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> manyToOneChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> manyToManyChildren=new HashMap<NodeLink,Node>();
    for (    NodeLink nodeLink : children.keySet()) {
      Relation.ForeignKey multiplicity=nodeLink.getMultiplicity();
switch (multiplicity) {
case ONE_TO_ONE:
        oneToOneChildren.put(nodeLink,children.get(nodeLink));
      break;
case ONE_TO_MANY:
    oneToManyChildren.put(nodeLink,children.get(nodeLink));
  break;
case MANY_TO_ONE:
manyToOneChildren.put(nodeLink,children.get(nodeLink));
break;
case MANY_TO_MANY:
manyToManyChildren.put(nodeLink,children.get(nodeLink));
break;
}
}
for (NodeLink nodeLink : oneToManyChildren.keySet()) {
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
if (!childNode.isTraversed() && childNode.isDirty()) {
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : manyToManyChildren.keySet()) {
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
if (node.isDirty() && !node.isTraversed()) {
JoinTableMetadata jtmd=(JoinTableMetadata)nodeLink.getLinkProperty(LinkProperty.JOIN_TABLE_METADATA);
String joinColumnName=(String)jtmd.getJoinColumns().toArray()[0];
String inverseJoinColumnName=(String)jtmd.getInverseJoinColumns().toArray()[0];
Object entityId=ObjectGraphBuilder.getEntityId(node.getNodeId());
Object childId=ObjectGraphBuilder.getEntityId(childNode.getNodeId());
Set<Object> childValues=new HashSet<Object>();
childValues.add(childId);
OPERATION operation=null;
if (node.getCurrentNodeState().getClass().equals(ManagedState.class)) {
operation=OPERATION.INSERT;
}
 else if (node.getCurrentNodeState().getClass().equals(RemovedState.class)) {
operation=OPERATION.DELETE;
}
pc.addJoinTableDataIntoMap(operation,jtmd.getJoinTableName(),joinColumnName,inverseJoinColumnName,node.getDataClass(),entityId,childValues);
}
if (!childNode.isTraversed() && childNode.isDirty()) {
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : oneToOneChildren.keySet()) {
if (!node.isTraversed() && node.isDirty()) {
node.setTraversed(true);
flushStack.push(node);
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : manyToOneChildren.keySet()) {
if (!node.isTraversed() && node.isDirty()) {
node.setTraversed(true);
flushStack.push(node);
}
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
Map<NodeLink,Node> parents=childNode.getParents();
for (NodeLink parentLink : parents.keySet()) {
Relation.ForeignKey multiplicity=parentLink.getMultiplicity();
if (multiplicity.equals(Relation.ForeignKey.MANY_TO_ONE)) {
Node parentNode=parents.get(parentLink);
if (!parentNode.isTraversed() && parentNode.isDirty()) {
addNodesToFlushStack(pc,parentNode);
}
}
}
if (!childNode.isTraversed() && childNode.isDirty()) {
addNodesToFlushStack(pc,childNode);
}
}
}
if (!node.isTraversed() && node.isDirty()) {
node.setTraversed(true);
flushStack.push(node);
}
}

Fixed version (ground truth):
/** 
 * Pushes <code>node</code> and its descendants recursively to flush stack  residing into persistence cache
 * @param pc
 * @param node
 */
public void addNodesToFlushStack(PersistenceCache pc,Node node){
  FlushStack flushStack=pc.getFlushStack();
  MainCache mainCache=(MainCache)pc.getMainCache();
  Map<NodeLink,Node> children=node.getChildren();
  if (children != null) {
    Map<NodeLink,Node> oneToOneChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> oneToManyChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> manyToOneChildren=new HashMap<NodeLink,Node>();
    Map<NodeLink,Node> manyToManyChildren=new HashMap<NodeLink,Node>();
    for (    NodeLink nodeLink : children.keySet()) {
      Relation.ForeignKey multiplicity=nodeLink.getMultiplicity();
switch (multiplicity) {
case ONE_TO_ONE:
        oneToOneChildren.put(nodeLink,children.get(nodeLink));
      break;
case ONE_TO_MANY:
    oneToManyChildren.put(nodeLink,children.get(nodeLink));
  break;
case MANY_TO_ONE:
manyToOneChildren.put(nodeLink,children.get(nodeLink));
break;
case MANY_TO_MANY:
manyToManyChildren.put(nodeLink,children.get(nodeLink));
break;
}
}
for (NodeLink nodeLink : oneToManyChildren.keySet()) {
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
if (!childNode.isTraversed()) {
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : manyToManyChildren.keySet()) {
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
if (node.isDirty() && !node.isTraversed()) {
JoinTableMetadata jtmd=(JoinTableMetadata)nodeLink.getLinkProperty(LinkProperty.JOIN_TABLE_METADATA);
String joinColumnName=(String)jtmd.getJoinColumns().toArray()[0];
String inverseJoinColumnName=(String)jtmd.getInverseJoinColumns().toArray()[0];
Object entityId=ObjectGraphBuilder.getEntityId(node.getNodeId());
Object childId=ObjectGraphBuilder.getEntityId(childNode.getNodeId());
Set<Object> childValues=new HashSet<Object>();
childValues.add(childId);
OPERATION operation=null;
if (node.getCurrentNodeState().getClass().equals(ManagedState.class)) {
operation=OPERATION.INSERT;
}
 else if (node.getCurrentNodeState().getClass().equals(RemovedState.class)) {
operation=OPERATION.DELETE;
}
pc.addJoinTableDataIntoMap(operation,jtmd.getJoinTableName(),joinColumnName,inverseJoinColumnName,node.getDataClass(),entityId,childValues);
}
if (!childNode.isTraversed()) {
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : oneToOneChildren.keySet()) {
if (!node.isTraversed()) {
node.setTraversed(true);
flushStack.push(node);
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
addNodesToFlushStack(pc,childNode);
}
}
for (NodeLink nodeLink : manyToOneChildren.keySet()) {
if (!node.isTraversed()) {
node.setTraversed(true);
flushStack.push(node);
}
Node childNode=mainCache.getNodeFromCache(nodeLink.getTargetNodeId());
Map<NodeLink,Node> parents=childNode.getParents();
for (NodeLink parentLink : parents.keySet()) {
Relation.ForeignKey multiplicity=parentLink.getMultiplicity();
if (multiplicity.equals(Relation.ForeignKey.MANY_TO_ONE)) {
Node parentNode=parents.get(parentLink);
if (!parentNode.isTraversed()) {
addNodesToFlushStack(pc,parentNode);
}
}
}
if (!childNode.isTraversed()) {
addNodesToFlushStack(pc,childNode);
}
}
}
if (!node.isTraversed()) {
node.setTraversed(true);
flushStack.push(node);
}
}