Quintiq file version 2.0
#parent: #root
Method GenerateNodes (
  shadow[SCVConfiguration] owner,
  ProductInStockingPointInPeriod outputpispip,
  shadow[SCVNode] outputnode,
  Number depth,
  Boolean isupstream
) id:Method_FormSupplyChainVisualization_GenerateNodes
{
  #keys: '[132894.0.861956399]'
  Body:
  [*
    // Create upstream / downstream nodes
    
    // Get PISPIPs of desired depth for PISPIPSCVNode
    outputs := this.GetInputOutputs( outputpispip, isupstream /*isupstream*/ );
    
    if( depth > 0 and not outputnode.IsDepthLimitMet() )
    {
      sourceNode := outputnode;
      
      traverse( outputs, Elements, output,
                owner.SCVNode( relsize ) <= owner.NodeLimit() )  
      {
        process := ifexpr( isupstream, output.AsProcessOutput(), output.AsProcessInput() );
    
        outputnode := this.FindCreateProcessNodeAndEdge( sourceNode, process, isupstream /*isupstream*/, depth );
        
        /*
         Leg transports A,B,C from Source to Destination will have ABC as input and ABC as output.
         If we don't have the filter in this traverse, we will get the upstream for 
         All input (A,B,C) instead of A or B or C.
        */
        pispips := this.GetPISPIPs( process, outputpispip, isupstream /*isupstream*/ ) 
        
        if( depth > 0 )
        { 
          traverse( pispips, Elements, pispip,
                    owner.SCVNode( relsize ) <= owner.NodeLimit() )
          {
            inputnode := outputnode;     
            
            // Only create the node if the pispip is not generated by the system
            if ( not pispip.ProductInStockingPoint_MP().IsSystem() )
            {                                                                   
              // Create a new node and also establish the link between the new node and the current node
              inputnode := this.FindCreatePISPIPNodeAndEdge( owner, inputnode, pispip, isupstream /*isupstream*/, process, depth )
              
              // Quantity to grab edge value, so that we can truncate branch if the value is 0
              quantity := 0.0;  
                                                                                                                                                                                                                                          
              this.ReturnEdgeLabel( ifexpr( isupstream, inputnode, outputnode ), ifexpr( isupstream, outputnode, inputnode ), quantity );       
              
              // Set depth to 0, meaning stop the drilling,
              if( quantity = 0.0 and owner.IsHideZeroSupplyPaths() )
              {
                inputnode.IsDepthLimitMet( true );
              }
            }
            
            depth := ifexpr( isupstream, owner.UpstreamDepthLimit(), owner.DownstreamDepthLimit() ) - inputnode.Depth();
            
            // Continue upstream, pass in the newly created node, because the next upstream node
            this.GenerateNodes( owner, pispip, inputnode, depth, isupstream )
          }
        }
        // Means we have hit the depth limit but there are more upstream nodes
        else if( depth = 0
                 and pispips.Size() > 0 )
        {
          outputnode.IsDepthLimitMet( true );    
        }    
      } 
    } 
    // Means we have hit the depth limit but there are more upstream nodes
    else if( depth = 0
             and outputs.Size() > 0 )
    {
      outputnode.IsDepthLimitMet( true );    
    }
  *]
}
