Skip to content

Commit d9ed7fb

Browse files
author
Mark Robinson
committed
Refactoring to enable URL manipulation to switch workflows
Also move various pieces of application logic out of controller layer
1 parent 986b075 commit d9ed7fb

File tree

9 files changed

+169
-108
lines changed

9 files changed

+169
-108
lines changed

src/main/java/org/commonwl/viewer/domain/cwl/CWLCollection.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,6 @@ private void addDoc(JsonNode newDoc, String fileName) {
197197
* @return The file name/key of the workflow
198198
*/
199199
private String findMainWorkflow() {
200-
// TODO: make this path dependant so it doesn't get messed up by duplicate filenames or graphs
201-
// Currently this strategy fails gracefully and returns the first workflow in the case of a graph
202-
203200
// Store the in degree of each workflow
204201
Map<String, Integer> inDegrees = new HashMap<String, Integer>();
205202
for (Map.Entry<String, JsonNode> doc : cwlDocs.entrySet()) {
@@ -301,8 +298,6 @@ private void fillStepRunTypes(Workflow workflow) {
301298
if (cwlDocs.containsKey(filePath.toString())) {
302299
JsonNode runDoc = cwlDocs.get(filePath.toString());
303300
step.setRunType(extractProcess(runDoc));
304-
} else {
305-
step.setRun(null);
306301
}
307302
}
308303
}

src/main/java/org/commonwl/viewer/services/GitHubService.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.eclipse.egit.github.core.client.GitHubClient;
2727
import org.eclipse.egit.github.core.service.CommitService;
2828
import org.eclipse.egit.github.core.service.ContentsService;
29-
import org.eclipse.egit.github.core.service.UserService;
3029
import org.springframework.beans.factory.annotation.Autowired;
3130
import org.springframework.beans.factory.annotation.Value;
3231
import org.springframework.stereotype.Service;
@@ -54,7 +53,6 @@ public class GitHubService {
5453

5554
// Github API services
5655
private final ContentsService contentsService;
57-
private final UserService userService;
5856
private final CommitService commitService;
5957

6058
// URL validation for directory links
@@ -73,7 +71,6 @@ public GitHubService(@Value("${githubAPI.authentication}") String authSetting,
7371
client.setOAuth2Token(token);
7472
}
7573
this.contentsService = new ContentsService(client);
76-
this.userService = new UserService(client);
7774
this.commitService = new CommitService(client);
7875
}
7976

@@ -101,16 +98,6 @@ public List<RepositoryContents> getContents(GithubDetails githubInfo) throws IOE
10198
githubInfo.getPath(), githubInfo.getBranch());
10299
}
103100

104-
/**
105-
* Get the details of a user from the Github API
106-
* @param username The username of the user we want to get data about
107-
* @return A user object containing the API information
108-
* @throws IOException Any API errors which may have occurred
109-
*/
110-
public User getUser(String username) throws IOException {
111-
return userService.getUser(username);
112-
}
113-
114101
/**
115102
* Download a single file from a Github repository
116103
* @param githubInfo The information to access the repository

src/main/java/org/commonwl/viewer/services/WorkflowFormValidator.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@
2020
package org.commonwl.viewer.services;
2121

2222
import org.commonwl.viewer.domain.GithubDetails;
23-
import org.eclipse.egit.github.core.RepositoryContents;
2423
import org.commonwl.viewer.domain.WorkflowForm;
24+
import org.eclipse.egit.github.core.RepositoryContents;
2525
import org.slf4j.Logger;
2626
import org.slf4j.LoggerFactory;
2727
import org.springframework.beans.factory.annotation.Autowired;
2828
import org.springframework.stereotype.Component;
2929
import org.springframework.validation.Errors;
3030
import org.springframework.validation.ValidationUtils;
31-
import org.springframework.validation.Validator;
3231

3332
import java.io.IOException;
3433
import java.util.List;
@@ -87,12 +86,12 @@ public GithubDetails validateAndParse(WorkflowForm form, Errors e) {
8786
} else {
8887
// The URL does not contain any .cwl files
8988
logger.error("No .cwl files found at Github URL");
90-
e.rejectValue("githubURL", "githubURL.missingWorkflow");
89+
e.rejectValue("githubURL", "githubURL.missingWorkflow", "No .cwl files were found in the specified Github directory");
9190
}
9291
} catch (IOException ex) {
9392
// Given repository/branch/path does not exist or API error occured
94-
logger.error(ex.getMessage());
95-
e.rejectValue("githubURL", "githubURL.apiError");
93+
logger.error("Github API Error", ex);
94+
e.rejectValue("githubURL", "githubURL.apiError", "API Error - does the specified Github directory exist?");
9695
}
9796
} else {
9897
// The Github URL is not valid

src/main/java/org/commonwl/viewer/services/WorkflowService.java

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
import org.commonwl.viewer.domain.GithubDetails;
2323
import org.commonwl.viewer.domain.Workflow;
2424
import org.commonwl.viewer.domain.cwl.CWLCollection;
25+
import org.commonwl.viewer.web.ROBundleNotFoundException;
2526
import org.slf4j.Logger;
2627
import org.slf4j.LoggerFactory;
2728
import org.springframework.beans.factory.annotation.Autowired;
2829
import org.springframework.beans.factory.annotation.Value;
30+
import org.springframework.data.domain.Page;
31+
import org.springframework.data.domain.Pageable;
2932
import org.springframework.stereotype.Service;
3033

3134
import java.io.File;
@@ -62,13 +65,91 @@ public WorkflowService(GitHubService githubService,
6265
this.totalFileSizeLimit = totalFileSizeLimit;
6366
}
6467

68+
/**
69+
* Gets a page of all workflows from the database
70+
* @param pageable The details of the page to be requested
71+
* @return The resulting page of the workflow entries
72+
*/
73+
public Page<Workflow> getPageOfWorkflows(Pageable pageable) {
74+
return workflowRepository.findAllByOrderByRetrievedOnDesc(pageable);
75+
}
76+
77+
/**
78+
* Get a workflow from the database by its ID
79+
* @param id The ID of the workflow
80+
* @return The model for the workflow
81+
*/
82+
public Workflow getWorkflow(String id) {
83+
return workflowRepository.findOne(id);
84+
}
85+
86+
/**
87+
* Get a workflow from the database, refreshing it if cache has expired
88+
* @param githubInfo Github information for the workflow
89+
* @return The workflow model associated with githubInfo
90+
*/
91+
public Workflow getWorkflow(GithubDetails githubInfo) {
92+
// Check database for existing workflow
93+
Workflow workflow = workflowRepository.findByRetrievedFrom(githubInfo);
94+
95+
// Create a new workflow if we do not have one already
96+
if (workflow != null) {
97+
// Delete the existing workflow if the cache has expired
98+
if (cacheExpired(workflow)) {
99+
// Update by trying to add a new workflow
100+
Workflow newWorkflow = createWorkflow(workflow.getRetrievedFrom());
101+
102+
// Only replace workflow if it could be successfully parsed
103+
if (newWorkflow == null) {
104+
logger.error("Could not parse updated workflow " + workflow.getID());
105+
} else {
106+
// Delete the existing workflow
107+
removeWorkflow(workflow);
108+
109+
// Save new workflow
110+
workflowRepository.save(newWorkflow);
111+
workflow = newWorkflow;
112+
}
113+
}
114+
}
115+
116+
return workflow;
117+
}
118+
119+
/**
120+
* Get the RO bundle for a Workflow, triggering re-download if it does not exist
121+
* @param id The ID of the workflow
122+
* @return The file containing the RO bundle
123+
* @throws ROBundleNotFoundException If the RO bundle was not found
124+
*/
125+
public File getROBundle(String id) throws ROBundleNotFoundException {
126+
// Get workflow from database
127+
Workflow workflow = getWorkflow(id);
128+
129+
// If workflow does not exist or the bundle doesn't yet
130+
if (workflow == null || workflow.getRoBundle() == null) {
131+
throw new ROBundleNotFoundException();
132+
}
133+
134+
// 404 error with retry if the file on disk does not exist
135+
File bundleDownload = new File(workflow.getRoBundle());
136+
if (!bundleDownload.exists()) {
137+
// Clear current RO bundle link and create a new one (async)
138+
workflow.setRoBundle(null);
139+
workflowRepository.save(workflow);
140+
generateROBundle(workflow);
141+
throw new ROBundleNotFoundException();
142+
}
143+
144+
return bundleDownload;
145+
}
146+
65147
/**
66148
* Builds a new workflow from cwl files fetched from Github
67149
* @param githubInfo Github information for the workflow
68150
* @return The constructed model for the Workflow
69151
*/
70-
public Workflow newWorkflowFromGithub(GithubDetails githubInfo) {
71-
152+
public Workflow createWorkflow(GithubDetails githubInfo) {
72153
try {
73154
// Get the sha hash from a branch reference
74155
String latestCommit = githubService.getCommitSha(githubInfo);
@@ -89,9 +170,11 @@ public Workflow newWorkflowFromGithub(GithubDetails githubInfo) {
89170
// This is Async so cannot just call constructor, needs intermediate as per Spring framework
90171
generateROBundle(workflowModel);
91172

173+
// Save to database
174+
workflowRepository.save(workflowModel);
175+
92176
// Return this model to be displayed
93177
return workflowModel;
94-
95178
} else {
96179
logger.error("No workflow could be found");
97180
}
@@ -106,7 +189,7 @@ public Workflow newWorkflowFromGithub(GithubDetails githubInfo) {
106189
* Generates the RO bundle for a Workflow and adds it to the model
107190
* @param workflow The workflow model to create a Research Object for
108191
*/
109-
public void generateROBundle(Workflow workflow) {
192+
private void generateROBundle(Workflow workflow) {
110193
try {
111194
ROBundleFactory.workflowROFromGithub(githubService, workflow.getRetrievedFrom(), workflow.getLastCommit());
112195
} catch (Exception ex) {
@@ -118,7 +201,7 @@ public void generateROBundle(Workflow workflow) {
118201
* Removes a workflow and its research object bundle
119202
* @param workflow The workflow to be deleted
120203
*/
121-
public void removeWorkflow(Workflow workflow) {
204+
private void removeWorkflow(Workflow workflow) {
122205
// Delete the Research Object Bundle from disk
123206
File roBundle = new File(workflow.getRoBundle());
124207
if (roBundle.delete()) {
@@ -139,7 +222,7 @@ public void removeWorkflow(Workflow workflow) {
139222
* @param workflow The cached workflow model
140223
* @return Whether or not there are new commits
141224
*/
142-
public boolean cacheExpired(Workflow workflow) {
225+
private boolean cacheExpired(Workflow workflow) {
143226
try {
144227
// Calculate expiration
145228
Calendar expireCal = Calendar.getInstance();
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.commonwl.viewer.web;
21+
22+
import org.springframework.http.HttpStatus;
23+
import org.springframework.web.bind.annotation.ResponseStatus;
24+
25+
/**
26+
* Exception thrown when a Research Object file does not exist
27+
*/
28+
@ResponseStatus(value = HttpStatus.NOT_FOUND)
29+
public class ROBundleNotFoundException extends RuntimeException {
30+
}

0 commit comments

Comments
 (0)