19
19
20
20
package org .commonwl .view .cwl ;
21
21
22
- import static org .apache .commons .io .FileUtils .readFileToString ;
23
-
24
- import java .io .ByteArrayInputStream ;
25
- import java .io .File ;
26
- import java .io .IOException ;
27
- import java .io .StringWriter ;
28
- import java .util .ArrayList ;
29
- import java .util .HashMap ;
30
- import java .util .Iterator ;
31
- import java .util .List ;
32
- import java .util .Map ;
33
-
22
+ import com .fasterxml .jackson .databind .JsonNode ;
23
+ import com .fasterxml .jackson .databind .ObjectMapper ;
24
+ import com .fasterxml .jackson .databind .node .ArrayNode ;
25
+ import com .fasterxml .jackson .databind .node .ObjectNode ;
26
+ import com .fasterxml .jackson .databind .node .TextNode ;
34
27
import org .apache .commons .io .FileUtils ;
35
28
import org .apache .commons .io .FilenameUtils ;
36
29
import org .apache .jena .iri .IRI ;
46
39
import org .commonwl .view .graphviz .ModelDotWriter ;
47
40
import org .commonwl .view .graphviz .RDFDotWriter ;
48
41
import org .commonwl .view .workflow .Workflow ;
42
+ import org .commonwl .view .workflow .WorkflowNotFoundException ;
49
43
import org .commonwl .view .workflow .WorkflowOverview ;
50
44
import org .slf4j .Logger ;
51
45
import org .slf4j .LoggerFactory ;
54
48
import org .springframework .stereotype .Service ;
55
49
import org .yaml .snakeyaml .Yaml ;
56
50
57
- import com .fasterxml .jackson .databind .JsonNode ;
58
- import com .fasterxml .jackson .databind .ObjectMapper ;
59
- import com .fasterxml .jackson .databind .node .ArrayNode ;
60
- import com .fasterxml .jackson .databind .node .ObjectNode ;
61
- import com .fasterxml .jackson .databind .node .TextNode ;
51
+ import java .io .ByteArrayInputStream ;
52
+ import java .io .File ;
53
+ import java .io .IOException ;
54
+ import java .io .StringWriter ;
55
+ import java .util .*;
56
+
57
+ import static org .apache .commons .io .FileUtils .readFileToString ;
62
58
63
59
/**
64
60
* Provides CWL parsing for workflows to gather an overview
@@ -114,12 +110,58 @@ public CWLService(RDFService rdfService,
114
110
this .singleFileSizeLimit = singleFileSizeLimit ;
115
111
}
116
112
113
+ /**
114
+ * Gets whether a file is packed using schema salad
115
+ * @param workflowFile The file to be parsed
116
+ * @return Whether the file is packed
117
+ */
118
+ public boolean isPacked (File workflowFile ) throws IOException {
119
+ if (workflowFile .length () > singleFileSizeLimit ) {
120
+ return false ;
121
+ }
122
+ String fileContent = readFileToString (workflowFile );
123
+ return fileContent .contains ("$graph" );
124
+ }
125
+
126
+ /**
127
+ * Gets a list of workflows from a packed CWL file
128
+ * @param packedFile The packed CWL file
129
+ * @return The list of workflow overviews
130
+ */
131
+ public List <WorkflowOverview > getWorkflowOverviewsFromPacked (File packedFile ) throws IOException {
132
+ if (packedFile .length () <= singleFileSizeLimit ) {
133
+ List <WorkflowOverview > overviews = new ArrayList <>();
134
+
135
+ JsonNode packedJson = yamlStringToJson (readFileToString (packedFile ));
136
+
137
+ if (packedJson .has (DOC_GRAPH )) {
138
+ for (JsonNode jsonNode : packedJson .get (DOC_GRAPH )) {
139
+ if (extractProcess (jsonNode ) == CWLProcess .WORKFLOW ) {
140
+ WorkflowOverview overview = new WorkflowOverview (jsonNode .get (ID ).asText (),
141
+ extractLabel (jsonNode ), extractDoc (jsonNode ));
142
+ overviews .add (overview );
143
+ }
144
+ }
145
+ } else {
146
+ throw new IOException ("The file given was not recognised as a packed CWL file" );
147
+ }
148
+
149
+ return overviews ;
150
+
151
+ } else {
152
+ throw new IOException ("File '" + packedFile .getName () + "' is over singleFileSizeLimit - " +
153
+ FileUtils .byteCountToDisplaySize (packedFile .length ()) + "/" +
154
+ FileUtils .byteCountToDisplaySize (singleFileSizeLimit ));
155
+ }
156
+ }
157
+
117
158
/**
118
159
* Gets the Workflow object from internal parsing
119
160
* @param workflowFile The workflow file to be parsed
161
+ * @param packedWorkflowId The ID of the workflow object if the file is packed
120
162
* @return The constructed workflow object
121
163
*/
122
- public Workflow parseWorkflowNative (File workflowFile ) throws IOException {
164
+ public Workflow parseWorkflowNative (File workflowFile , String packedWorkflowId ) throws IOException {
123
165
124
166
// Check file size limit before parsing
125
167
long fileSizeBytes = workflowFile .length ();
@@ -128,16 +170,30 @@ public Workflow parseWorkflowNative(File workflowFile) throws IOException {
128
170
// Parse file as yaml
129
171
JsonNode cwlFile = yamlStringToJson (readFileToString (workflowFile ));
130
172
131
- // If the CWL file is packed there can be multiple workflows in a file
132
- Map <String , JsonNode > packedFiles = new HashMap <>();
133
- if (cwlFile .has (DOC_GRAPH )) {
134
- // Packed CWL, find the first subelement which is a workflow and take it
135
- for (JsonNode jsonNode : cwlFile .get (DOC_GRAPH )) {
136
- packedFiles .put (jsonNode .get (ID ).asText (), jsonNode );
137
- if (extractProcess (jsonNode ) == CWLProcess .WORKFLOW ) {
138
- cwlFile = jsonNode ;
173
+ // Check packed workflow occurs
174
+ if (packedWorkflowId != null ) {
175
+ boolean found = false ;
176
+ if (cwlFile .has (DOC_GRAPH )) {
177
+ for (JsonNode jsonNode : cwlFile .get (DOC_GRAPH )) {
178
+ if (extractProcess (jsonNode ) == CWLProcess .WORKFLOW ) {
179
+ String currentId = jsonNode .get (ID ).asText ();
180
+ if (currentId .startsWith ("#" )) {
181
+ currentId = currentId .substring (1 );
182
+ }
183
+ if (currentId .equals (packedWorkflowId )) {
184
+ cwlFile = jsonNode ;
185
+ found = true ;
186
+ break ;
187
+ }
188
+ }
139
189
}
140
190
}
191
+ if (!found ) throw new WorkflowNotFoundException ();
192
+ } else {
193
+ // Check the current json node is a workflow
194
+ if (extractProcess (cwlFile ) != CWLProcess .WORKFLOW ) {
195
+ throw new WorkflowNotFoundException ();
196
+ }
141
197
}
142
198
143
199
// Use filename for label if there is no defined one
@@ -150,10 +206,6 @@ public Workflow parseWorkflowNative(File workflowFile) throws IOException {
150
206
Workflow workflowModel = new Workflow (label , extractDoc (cwlFile ), getInputs (cwlFile ),
151
207
getOutputs (cwlFile ), getSteps (cwlFile ), null );
152
208
153
- if (packedFiles .size () > 0 ) {
154
- workflowModel .setPackedWorkflowID (cwlFile .get (ID ).asText ());
155
- }
156
-
157
209
workflowModel .setCwltoolVersion (cwlTool .getVersion ());
158
210
159
211
// Generate DOT graph
@@ -186,7 +238,7 @@ public Workflow parseWorkflowWithCwltool(Workflow basicModel,
186
238
File workflowFile ) throws CWLValidationException {
187
239
GitDetails gitDetails = basicModel .getRetrievedFrom ();
188
240
String latestCommit = basicModel .getLastCommit ();
189
- String packedWorkflowID = basicModel . getPackedWorkflowID ();
241
+ String packedWorkflowID = gitDetails . getPackedId ();
190
242
191
243
// Get paths to workflow
192
244
String url = gitDetails .getUrl (latestCommit ).replace ("https://" , "" );
@@ -405,13 +457,19 @@ public WorkflowOverview getWorkflowOverview(File file) throws IOException {
405
457
JsonNode cwlFile = yamlStringToJson (readFileToString (file ));
406
458
407
459
// If the CWL file is packed there can be multiple workflows in a file
460
+ int packedCount = 0 ;
408
461
if (cwlFile .has (DOC_GRAPH )) {
409
462
// Packed CWL, find the first subelement which is a workflow and take it
410
463
for (JsonNode jsonNode : cwlFile .get (DOC_GRAPH )) {
411
464
if (extractProcess (jsonNode ) == CWLProcess .WORKFLOW ) {
412
465
cwlFile = jsonNode ;
466
+ packedCount ++;
413
467
}
414
468
}
469
+ if (packedCount > 1 ) {
470
+ return new WorkflowOverview ("/" + file .getName (), "Packed file" ,
471
+ "contains " + packedCount + " workflows" );
472
+ }
415
473
}
416
474
417
475
// Can only make an overview if this is a workflow
@@ -423,7 +481,7 @@ public WorkflowOverview getWorkflowOverview(File file) throws IOException {
423
481
}
424
482
425
483
// Return the constructed overview
426
- return new WorkflowOverview (file .getName (), label , extractDoc (cwlFile ));
484
+ return new WorkflowOverview ("/" + file .getName (), label , extractDoc (cwlFile ));
427
485
} else {
428
486
// Return null if not a workflow file
429
487
return null ;
0 commit comments