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.ws.params.ParamManager;
12 import jalview.ws2.actions.alignment.AlignmentAction;
13 import jalview.ws2.actions.annotation.AnnotationAction;
14 import jalview.ws2.api.WebService;
15 import jalview.ws2.client.api.AbstractWebServiceDiscoverer;
16 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
17 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
19 public class SlivkaWSDiscoverer extends AbstractWebServiceDiscoverer
21 private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
23 private static final URL DEFAULT_URL;
28 DEFAULT_URL = new URL("https://www.compbio.dundee.ac.uk/slivka/");
29 } catch (MalformedURLException e)
31 throw new AssertionError(e);
35 private static SlivkaWSDiscoverer instance = null;
37 private static ParamManager paramManager = null;
39 private SlivkaWSDiscoverer()
43 public static SlivkaWSDiscoverer getInstance()
46 instance = new SlivkaWSDiscoverer();
50 public static void setParamManager(ParamManager manager)
52 paramManager = manager;
56 public int getStatusForUrl(URL url)
60 List<?> services = new SlivkaClient(url.toString()).getServices();
61 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
62 } catch (IOException e)
64 Cache.log.error("slivka could not retrieve services from " + url, e);
65 return STATUS_INVALID;
70 protected String getUrlsPropertyKey()
72 return SLIVKA_HOST_URLS;
76 protected URL getDefaultUrl()
82 protected List<WebService<?>> fetchServices(URL url) throws IOException
84 ArrayList<WebService<?>> allServices = new ArrayList<>();
85 SlivkaClient slivkaClient;
88 slivkaClient = new SlivkaClient(url.toURI());
89 } catch (URISyntaxException e)
91 throw new MalformedURLException(e.getMessage());
93 for (var slivkaService : slivkaClient.getServices())
95 int serviceClass = getServiceClass(slivkaService);
96 if (serviceClass == SERVICE_CLASS_MSA)
98 var wsb = WebService.<AlignmentAction> newBuilder();
99 initServiceBuilder(slivkaService, wsb);
100 wsb.category("Alignment");
101 wsb.interactive(false);
102 wsb.actionClass(AlignmentAction.class);
103 var msaService = wsb.build();
105 boolean canRealign = msaService.getName().contains("lustal");
106 var client = new SlivkaAlignmentWSClient(slivkaService);
107 var actionBuilder = AlignmentAction.newBuilder(client);
108 actionBuilder.name("Alignment");
109 actionBuilder.webService(msaService);
111 actionBuilder.subcategory("Align");
112 actionBuilder.minSequences(2);
113 msaService.addAction(actionBuilder.build());
116 actionBuilder.name("Re-alignment");
117 actionBuilder.subcategory("Realign");
118 actionBuilder.submitGaps(true);
119 msaService.addAction(actionBuilder.build());
121 allServices.add(msaService);
123 else if (serviceClass == SERVICE_CLASS_PROT_SEQ_ANALYSIS)
125 var wsb = WebService.<AnnotationAction> newBuilder();
126 initServiceBuilder(slivkaService, wsb);
127 wsb.category("Protein Disorder");
128 wsb.interactive(false);
129 wsb.actionClass(AnnotationAction.class);
130 var psaService = wsb.build();
131 var client = new SlivkaAnnotationWSClient(slivkaService);
132 var actionBuilder = AnnotationAction.newBuilder(client);
133 actionBuilder.webService(psaService);
134 actionBuilder.name("Analysis");
135 psaService.addAction(actionBuilder.build());
136 allServices.add(psaService);
138 else if (serviceClass == SERVICE_CLASS_CONSERVATION)
140 var wsb = WebService.<AnnotationAction> newBuilder();
141 initServiceBuilder(slivkaService, wsb);
142 wsb.category("Conservation");
143 wsb.interactive(true);
144 wsb.actionClass(AnnotationAction.class);
145 var conService = wsb.build();
146 var client = new SlivkaAnnotationWSClient(slivkaService);
147 var actionBuilder = AnnotationAction.newBuilder(client);
148 actionBuilder.webService(conService);
149 actionBuilder.name("");
150 actionBuilder.alignmentAnalysis(true);
151 actionBuilder.requireAlignedSequences(true);
152 actionBuilder.filterSymbols(true);
153 conService.addAction(actionBuilder.build());
154 allServices.add(conService);
156 else if (serviceClass == SERVICE_CLASS_RNA_SEC_STR_PRED)
168 private void initServiceBuilder(SlivkaService service, WebService.Builder<?> wsBuilder)
172 wsBuilder.url(service.getUrl().toURL());
173 } catch (MalformedURLException e)
177 wsBuilder.clientName("slivka");
178 wsBuilder.name(service.getName());
179 wsBuilder.description(service.getDescription());
180 var storeBuilder = new SlivkaParamStoreFactory(service, paramManager);
181 wsBuilder.paramDatastore(storeBuilder.createParamDatastore());
184 static final int SERVICE_CLASS_UNSUPPORTED = -1;
186 static final int SERVICE_CLASS_MSA = 1;
188 static final int SERVICE_CLASS_RNA_SEC_STR_PRED = 2;
190 static final int SERVICE_CLASS_CONSERVATION = 3;
192 static final int SERVICE_CLASS_PROT_SEQ_ANALYSIS = 4;
194 static final int SERVICE_CLASS_PROT_SEC_STR_PRED = 5;
197 * Scan service classifiers starting with operation :: analysis to decide the
200 * @return service class flag
202 private static int getServiceClass(SlivkaService service)
204 for (String classifier : service.getClassifiers())
206 String[] path = classifier.split("\\s*::\\s*");
207 if (path.length < 3 || !path[0].equalsIgnoreCase("operation") ||
208 !path[1].equalsIgnoreCase("analysis"))
210 // classifier is operation :: analysis :: *
211 var tail = path[path.length - 1].toLowerCase();
214 case "multiple sequence alignment":
215 return SERVICE_CLASS_MSA;
216 case "rna secondary structure prediction":
217 return SERVICE_CLASS_RNA_SEC_STR_PRED;
218 case "sequence alignment analysis (conservation)":
219 return SERVICE_CLASS_CONSERVATION;
220 case "protein sequence analysis":
221 return SERVICE_CLASS_PROT_SEQ_ANALYSIS;
222 case "protein secondary structure prediction":
223 return SERVICE_CLASS_PROT_SEC_STR_PRED;
226 return SERVICE_CLASS_UNSUPPORTED;