| Quintiq file version 2.0 | 
| #parent: #root | 
| Method GenerateNodes ( | 
|   output owning 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( &owner, 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( &owner, 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 );     | 
|     } | 
|   *] | 
| } |