@@ -100,6 +100,53 @@ def raw_wfb_to_lean_wfb(inp: Json) -> Json:
100100 return inp_restrict
101101
102102
103+ def get_topological_order (links : list [dict [str , str ]]) -> list [str ]:
104+ """Get topological order of the nodes from links"""
105+ # Create adjacency list representation
106+ graph : dict [str , list [str ]] = {}
107+ in_degree : dict [str , int ] = {}
108+
109+ # Initialize all nodes with 0 in-degree
110+ for link in links :
111+ source = link ['sourceId' ]
112+ target = link ['targetId' ]
113+ if source not in graph :
114+ graph [source ] = []
115+ if target not in graph :
116+ graph [target ] = []
117+ if source not in in_degree :
118+ in_degree [source ] = 0
119+ if target not in in_degree :
120+ in_degree [target ] = 0
121+
122+ # Build the graph and count in-degrees
123+ for link in links :
124+ source = link ['sourceId' ]
125+ target = link ['targetId' ]
126+ graph [source ].append (target )
127+ in_degree [target ] += 1
128+
129+ # Initialize queue with nodes that have 0 in-degree
130+ queue : list [str ] = []
131+ for node in in_degree :
132+ if in_degree [node ] == 0 :
133+ queue .append (node )
134+
135+ # Process the queue
136+ result : list [str ] = []
137+ while queue :
138+ node = queue .pop (0 )
139+ result .append (node )
140+
141+ # Reduce in-degree of neighbors
142+ for neighbor in graph [node ]:
143+ in_degree [neighbor ] -= 1
144+ if in_degree [neighbor ] == 0 :
145+ queue .append (neighbor )
146+
147+ return result
148+
149+
103150def wfb_to_wic (inp : Json ) -> Cwl :
104151 """Convert lean wfb json to compliant wic"""
105152 # non-schema preserving changes
@@ -155,18 +202,21 @@ def wfb_to_wic(inp: Json) -> Cwl:
155202 for dfk in diff_keys :
156203 tgt_node ['in' ][dfk ] = yaml .load ('!ii ' + str (tgt_node ['in' ][dfk ]), Loader = wic_loader ())
157204
158- for node in inp_restrict ['nodes' ]:
159- # just reuse name as node's pluginId, wic id is same as wfb name
160- node ['id' ] = node ['pluginId' ].split ('@' )[0 ].replace ('/' , '_' )
161- node .pop ('pluginId' , None )
162-
163205 workflow_temp : Cwl = {}
164206 if inp_restrict ["links" ] != []:
207+ node_order = get_topological_order (inp_restrict ["links" ])
165208 workflow_temp ["steps" ] = []
166- for node in inp_restrict ["nodes" ]:
167- workflow_temp ["steps" ].append (node ) # node["cwlScript"] # Assume dict form
209+ for id in node_order :
210+ node = next ((n for n in inp_restrict ["nodes" ] if n ["id" ] == id ), None )
211+ if node :
212+ # just reuse name as node's pluginId, wic id is same as wfb name
213+ node ['id' ] = node ['pluginId' ].split ('@' )[0 ].replace ('/' , '_' )
214+ node .pop ('pluginId' , None )
215+ workflow_temp ["steps" ].append (node )
168216 else : # A single node workflow
169217 node = inp_restrict ["nodes" ][0 ]
218+ node ['id' ] = node ['pluginId' ].split ('@' )[0 ].replace ('/' , '_' )
219+ node .pop ('pluginId' , None )
170220 if node .get ("cwlScript" ):
171221 workflow_temp = node ["cwlScript" ]
172222 else :
0 commit comments