1 package jalview.ws2.client.slivka;
3 import java.io.IOException;
4 import java.net.MalformedURLException;
5 import java.net.URISyntaxException;
7 import java.util.ArrayList;
10 import jalview.bin.Cache;
11 import jalview.bin.Console;
12 import jalview.ws.params.ParamManager;
13 import jalview.ws2.actions.alignment.AlignmentAction;
14 import jalview.ws2.actions.annotation.AnnotationAction;
15 import jalview.ws2.api.WebService;
16 import jalview.ws2.client.api.AbstractWebServiceDiscoverer;
17 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
18 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
20 public class SlivkaWSDiscoverer extends AbstractWebServiceDiscoverer
22 private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
24 private static final URL DEFAULT_URL;
29 DEFAULT_URL = new URL("https://www.compbio.dundee.ac.uk/slivka/");
30 } catch (MalformedURLException e)
32 throw new AssertionError(e);
36 private static SlivkaWSDiscoverer instance = null;
38 private static ParamManager paramManager = null;
40 private SlivkaWSDiscoverer()
44 public static SlivkaWSDiscoverer getInstance()
47 instance = new SlivkaWSDiscoverer();
51 public static void setParamManager(ParamManager manager)
53 paramManager = manager;
57 public int getStatusForUrl(URL url)
61 List<?> services = new SlivkaClient(url.toString()).getServices();
62 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
63 } catch (IOException e)
65 Console.error("slivka could not retrieve services from " + url, e);
66 return STATUS_INVALID;
71 protected String getUrlsPropertyKey()
73 return SLIVKA_HOST_URLS;
77 protected URL getDefaultUrl()
83 protected List<WebService<?>> fetchServices(URL url) throws IOException
85 ArrayList<WebService<?>> allServices = new ArrayList<>();
86 SlivkaClient slivkaClient;
89 slivkaClient = new SlivkaClient(url.toURI());
90 } catch (URISyntaxException e)
92 throw new MalformedURLException(e.getMessage());
94 for (var slivkaService : slivkaClient.getServices())
96 int serviceClass = getServiceClass(slivkaService);
97 if (serviceClass == SERVICE_CLASS_MSA)
99 var wsb = WebService.<AlignmentAction> newBuilder();
100 initServiceBuilder(slivkaService, wsb);
101 wsb.category("Alignment");
102 wsb.interactive(false);
103 wsb.actionClass(AlignmentAction.class);
104 var msaService = wsb.build();
106 boolean canRealign = msaService.getName().contains("lustal");
107 var client = new SlivkaAlignmentWSClient(slivkaService);
108 var actionBuilder = AlignmentAction.newBuilder(client);
109 actionBuilder.name("Alignment");
110 actionBuilder.webService(msaService);
112 actionBuilder.subcategory("Align");
113 actionBuilder.minSequences(2);
114 msaService.addAction(actionBuilder.build());
117 actionBuilder.name("Re-alignment");
118 actionBuilder.subcategory("Realign");
119 actionBuilder.submitGaps(true);
120 msaService.addAction(actionBuilder.build());
122 allServices.add(msaService);
124 else if (serviceClass == SERVICE_CLASS_PROT_SEQ_ANALYSIS)
126 var wsb = WebService.<AnnotationAction> newBuilder();
127 initServiceBuilder(slivkaService, wsb);
128 wsb.category("Protein Disorder");
129 wsb.interactive(false);
130 wsb.actionClass(AnnotationAction.class);
131 var psaService = wsb.build();
132 var client = new SlivkaAnnotationWSClient(slivkaService);
133 var actionBuilder = AnnotationAction.newBuilder(client);
134 actionBuilder.webService(psaService);
135 actionBuilder.name("Analysis");
136 psaService.addAction(actionBuilder.build());
137 allServices.add(psaService);
139 else if (serviceClass == SERVICE_CLASS_CONSERVATION)
141 var wsb = WebService.<AnnotationAction> newBuilder();
142 initServiceBuilder(slivkaService, wsb);
143 wsb.category("Conservation");
144 wsb.interactive(true);
145 wsb.actionClass(AnnotationAction.class);
146 var conService = wsb.build();
147 var client = new SlivkaAnnotationWSClient(slivkaService);
148 var actionBuilder = AnnotationAction.newBuilder(client);
149 actionBuilder.webService(conService);
150 actionBuilder.name("");
151 actionBuilder.alignmentAnalysis(true);
152 actionBuilder.requireAlignedSequences(true);
153 actionBuilder.filterSymbols(true);
154 conService.addAction(actionBuilder.build());
155 allServices.add(conService);
157 else if (serviceClass == SERVICE_CLASS_RNA_SEC_STR_PRED)
159 var wsb = WebService.<AnnotationAction> newBuilder();
160 initServiceBuilder(slivkaService, wsb);
161 wsb.category("Secondary Structure Prediction");
162 wsb.interactive(true);
163 wsb.actionClass(AnnotationAction.class);
164 var predService = wsb.build();
165 var client = new SlivkaAnnotationWSClient(slivkaService);
166 var actionBuilder = AnnotationAction.newBuilder(client);
167 actionBuilder.webService(predService);
168 actionBuilder.name("Prediction");
169 actionBuilder.minSequences(2);
170 actionBuilder.allowNucleotide(true);
171 actionBuilder.allowProtein(false);
172 actionBuilder.alignmentAnalysis(true);
173 actionBuilder.requireAlignedSequences(true);
174 actionBuilder.filterSymbols(false);
175 predService.addAction(actionBuilder.build());
176 allServices.add(predService);
186 private void initServiceBuilder(SlivkaService service, WebService.Builder<?> wsBuilder)
190 wsBuilder.url(service.getClient().getUrl().toURL());
191 } catch (MalformedURLException e)
195 wsBuilder.clientName("slivka");
196 wsBuilder.name(service.getName());
197 wsBuilder.description(service.getDescription());
198 var storeBuilder = new SlivkaParamStoreFactory(service, paramManager);
199 wsBuilder.paramDatastore(storeBuilder.createParamDatastore());
202 static final int SERVICE_CLASS_UNSUPPORTED = -1;
204 static final int SERVICE_CLASS_MSA = 1;
206 static final int SERVICE_CLASS_RNA_SEC_STR_PRED = 2;
208 static final int SERVICE_CLASS_CONSERVATION = 3;
210 static final int SERVICE_CLASS_PROT_SEQ_ANALYSIS = 4;
212 static final int SERVICE_CLASS_PROT_SEC_STR_PRED = 5;
215 * Scan service classifiers starting with operation :: analysis to decide the
218 * @return service class flag
220 private static int getServiceClass(SlivkaService service)
222 for (String classifier : service.getClassifiers())
224 String[] path = classifier.split("\\s*::\\s*");
225 if (path.length < 3 || !path[0].equalsIgnoreCase("operation") ||
226 !path[1].equalsIgnoreCase("analysis"))
228 // classifier is operation :: analysis :: *
229 var tail = path[path.length - 1].toLowerCase();
232 case "multiple sequence alignment":
233 return SERVICE_CLASS_MSA;
234 case "rna secondary structure prediction":
235 return SERVICE_CLASS_RNA_SEC_STR_PRED;
236 case "sequence alignment analysis (conservation)":
237 return SERVICE_CLASS_CONSERVATION;
238 case "protein sequence analysis":
239 return SERVICE_CLASS_PROT_SEQ_ANALYSIS;
240 case "protein secondary structure prediction":
241 return SERVICE_CLASS_PROT_SEC_STR_PRED;
244 return SERVICE_CLASS_UNSUPPORTED;