From 64e13dcd5c27aa9f347a60de37f39636c6cf497c Mon Sep 17 00:00:00 2001
From: George Marchment <georgemarchment@yahoo.fr>
Date: Fri, 3 Jan 2025 11:53:29 +0100
Subject: [PATCH] Started working on a good version for the detection of the
 broken subworkflows

---
 src/channel.py  |   2 +-
 src/workflow.py | 118 ++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 99 insertions(+), 21 deletions(-)

diff --git a/src/channel.py b/src/channel.py
index 1e9cdfb..c51a205 100644
--- a/src/channel.py
+++ b/src/channel.py
@@ -23,7 +23,7 @@ class Channel(Nextflow_Building_Blocks):
         self.sink = []
 
 
-    def get_code(self):
+    def get_code(self, get_OG = True):
         """Method that returns the channels code
 
         Keyword arguments:
diff --git a/src/workflow.py b/src/workflow.py
index 9dcb913..2b6e538 100644
--- a/src/workflow.py
+++ b/src/workflow.py
@@ -810,6 +810,46 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
                 raise Exception("This shouldn't happen")
         return code
 
+    #I do not recommand that the dev uses the same name for the channels inside and outside the channels
+    #Since the local channels become local at the upper level
+    def rewrite_subworkflow_call(seld, code, subworklfow):
+        print(subworklfow.get_name())
+        #Remove the defintion from the code
+        code = code.replace(subworklfow.get_code(), "")
+        OG_call = subworklfow.get_call()
+        if(len(OG_call)>1):
+            raise Exception("This shouldn't happen")
+        OG_call = OG_call[0]
+        OG_body = subworklfow.get_work()
+        
+        #REPLACE HEADER TAKES
+        subworkflow_takes = subworklfow.get_takes()
+        parameters = OG_call.get_parameters()
+        if(len(subworkflow_takes)!=len(parameters)):
+            raise Exception("This shouldn't happen -> the same number of parameters should be kept")
+        #This is to replace the paramters and the takes
+        new_header = ""
+        for i in range(len(parameters)):
+            param = parameters[i]
+            takes = subworkflow_takes[i].get_gives()[0]
+            if(takes.get_code()!=param.get_code(get_OG = True)):
+                new_header+=f"{takes.get_code()} = {param.get_code(get_OG = True)}"
+        
+        code = code.replace(OG_call.get_code(get_OG = True), f"{new_header}\n\n{OG_body}")
+
+        #REPLACE THE EMITS
+        emits = subworklfow.get_emit()
+        for o in emits:
+            origin = o.get_origins()[0]
+            gives = o.get_gives()
+            #TODO finish this -> i think that the gives is empty
+            print(o.get_type())
+            print(o.get_code(), origin.get_code(), gives)
+            
+
+        #print(code)
+        return code
+
 
 
     #Conert workflow to user_view only makes sense when the option duplicate is activated -> otherwise is doesn't make sense + it makes the analysis way more complicated
@@ -832,7 +872,7 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
             self.nextflow_file.generate_user_view(relevant_processes = relevant_processes, processes_2_remove =  [])
             clusters = self.nextflow_file.graph.get_clusters_from_user_view()
 
-            """#DETERMING WHICH SUBWORKFLOWS ARE BROKEN WITH THE CLUSTER
+            #DETERMING WHICH SUBWORKFLOWS ARE BROKEN WITH THE CLUSTER
             #Creating the clusters with calls instead of processes or subworkflows
             set_clusters_with_calls = []
             for c in clusters:
@@ -847,30 +887,68 @@ George Marchment, Bryan Brancotte, Marie Schmit, Frédéric Lemoine, Sarah Cohen
                             raise Exception("This shouldn't happen")
                         tab.append(call[0])
                 set_clusters_with_calls.append(set(tab))
-            print(set_clusters_with_calls)
 
+            #Getting subworkflows to executors
             subworkflow_2_executors = {}
             for sub in self.get_subworkflows_called():
                 dico = {}
                 sub.get_all_executors(dico)
-                subworkflow_2_executors[sub.get_name()] = set(list(dico.keys()))
-            print(subworkflow_2_executors)
-
-            def check_subworkflow_intact(original_sets, new_sets):
-                results = {}
-                for sub in original_sets:
-                    original = original_sets[sub]
-                    #temp = []
-                    #for new in new_sets:
-                    #    print(original, new, new.issubset(original))
-                    #    #temp.append(original.issubset(new))
-                    #print(temp)
-                    intact = all(new.issubset(original) for new in new_sets)
-                    results[sub] = intact
-                return results
-
-            print(check_subworkflow_intact(subworkflow_2_executors, set_clusters_with_calls))
-            1/0"""
+                temp = set(list(dico.keys()))
+                subworkflow_2_executors[sub] = []
+                for ele in temp:
+                    #Cannot add calls to subworkflows -> they are already present by definition
+                    if(ele.get_type()=="Call" and ele.get_first_element_called().get_type()=="Subworkflow"):
+                        None
+                        #We don't add it
+                    else:
+                        subworkflow_2_executors[sub].append(ele)
+                #subworkflow_2_executors[sub.get_name()] = set(list(dico.keys()))
+
+            def get_workflows_broken(subworkflow_2_executors, set_clusters_with_calls):
+                broken_subworkflows = []
+                for sub in subworkflow_2_executors:
+                    #You want this list (set) to be equal to subworkflow_2_executors[sub]
+                    elements_in_sub_with_clusters = []
+                    for cluster in set_clusters_with_calls:
+                        if(len(elements_in_sub_with_clusters)>len(subworkflow_2_executors[sub])):
+                            break
+                        for c in cluster:
+                            if(len(elements_in_sub_with_clusters)>len(subworkflow_2_executors[sub])):
+                                break
+                            if(c in subworkflow_2_executors[sub]):
+                                elements_in_sub_with_clusters+=list(cluster)
+                                break
+                    if(set(elements_in_sub_with_clusters)==set(subworkflow_2_executors[sub])):
+                        None
+                        #This means that the subworkflow is Intact
+                    else:
+                        #This means that the subworkflow is broken
+                        broken_subworkflows.append(sub)
+                return broken_subworkflows
+
+            broken_subworkflows = get_workflows_broken(subworkflow_2_executors, set_clusters_with_calls)
+            
+            #Rewrite broken subworkflows
+            for sub in broken_subworkflows:
+                code = self.rewrite_subworkflow_call(code, sub)
+                
+            1/0
+
+            #def check_subworkflow_intact(original_sets, new_sets):
+            #    results = {}
+            #    for sub in original_sets:
+            #        original = original_sets[sub]
+            #        #temp = []
+            #        #for new in new_sets:
+            #        #    print(original, new, new.issubset(original))
+            #        #    #temp.append(original.issubset(new))
+            #        #print(temp)
+            #        intact = all(new.issubset(original) for new in new_sets)
+            #        results[sub] = intact
+            #    return results
+
+            #print(check_subworkflow_intact(subworkflow_2_executors, set_clusters_with_calls))
+            1/0
 
             #cluster_2_subworkflows = []
             #print(clusters)
-- 
GitLab