From 0740cd1a6899f88e8da16e20fb3bcd886fd6caa7 Mon Sep 17 00:00:00 2001 From: jprocter Date: Tue, 30 Aug 2011 11:28:27 +0100 Subject: [PATCH] JAL-715 serialise and deserialise multiple rest client strings as a jalview property --- src/jalview/ws/rest/RestClient.java | 64 +++++++++++++- src/jalview/ws/rest/RestServiceDescription.java | 108 ++++++++++++++++++----- 2 files changed, 148 insertions(+), 24 deletions(-) diff --git a/src/jalview/ws/rest/RestClient.java b/src/jalview/ws/rest/RestClient.java index 114f51a..ee23790 100644 --- a/src/jalview/ws/rest/RestClient.java +++ b/src/jalview/ws/rest/RestClient.java @@ -7,6 +7,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import java.util.Hashtable; +import java.util.Vector; import javax.swing.JMenu; import javax.swing.JMenuItem; @@ -341,11 +342,54 @@ public class RestClient extends WSClient implements WSClientI, return true; } + protected static Vector services=null; public static RestClient[] getRestClients() { - return new RestClient[] { makeShmmrRestClient() }; + if (services==null) + { + services = new Vector(); + try { + for (RestServiceDescription descr: RestServiceDescription.parseDescriptions(jalview.bin.Cache.getDefault("RSBS_SERVICES",makeShmmrRestClient().service.toString()))) + { + services.add(descr.toString()); + } + } + catch (Exception ex) { + System.err.println("Serious - RSBS descriptions in user preferences are corrupt!"); + ex.printStackTrace(); + } + + } + RestClient[] lst = new RestClient[services.size()]; + int i=0; + for (String svc:services) { + lst[i++] = new RestClient(new RestServiceDescription(svc)); + } + return lst; + } + public static void main(String args[]) + { + try { + RestClient[] clients = getRestClients(); + System.out.println("Got "+clients.length+" clients."); + int i=0; + Vector urls=new Vector(); + for (RestClient cl:clients) { + System.out.println(""+(++i)+": "+cl.service.toString()); + urls.add(cl.service.toString()); + } + setRsbsServices(urls); + if (clients.length!=getRestClients().length) + { + System.err.println("Failed. Differing numbers of clients when stringified and parsed again."); + } + + } catch (Throwable x) + { + System.err.println("Failed. Unexpected exception."); + x.printStackTrace(); + } } - public String getAction() { return service.details.Action; @@ -356,4 +400,20 @@ public class RestClient extends WSClient implements WSClientI, return service; } + public static Vector getRsbsDescriptions() + { + Vector rsbsDescrs = new Vector(); + for (RestClient rsbs:getRestClients()) + { + rsbsDescrs.add(rsbs.getRestDescription().toString()); + } + return rsbsDescrs; + } + + public static void setRsbsServices(Vector rsbsUrls) + { + // TODO: consider validating services ? + services = new Vector(rsbsUrls); + } + } diff --git a/src/jalview/ws/rest/RestServiceDescription.java b/src/jalview/ws/rest/RestServiceDescription.java index dec4d7c..9f4495e 100644 --- a/src/jalview/ws/rest/RestServiceDescription.java +++ b/src/jalview/ws/rest/RestServiceDescription.java @@ -49,6 +49,13 @@ import com.sun.tools.doclets.internal.toolkit.util.DocFinder.Output; public class RestServiceDescription { /** + * create a new rest service description ready to be configured + */ + public RestServiceDescription() + { + + } + /** * @param details * @param postUrl * @param urlSuffix @@ -501,6 +508,7 @@ public class RestServiceDescription ; boolean valid = true; String val = null; + int l = warnings.length(); int i; for (String prop : props) { @@ -538,12 +546,11 @@ public class RestServiceDescription } if (prop.equals("returns")) { - int l = warnings.length(); _configureOutputFormatFrom(val, warnings); - valid = (l != warnings.length()); } } - return valid; + // return true if valid is true and warning buffer was not appended to. + return valid && (l == warnings.length()); } private String _genOutputFormatString() @@ -598,18 +605,18 @@ public class RestServiceDescription private String getServiceIOProperties() { - String[] vls = new String[] - { isHseparable() ? "hseparable" : "", - isVseparable() ? "vseparable" : "", - (new String("gapCharacter='" + gapCharacter + "'")), - (new String("returns='" + _genOutputFormatString() + "'")) }; - - return arrayToSeparatorList(vls, ","); + ArrayList vls = new ArrayList(); + if (isHseparable()) { vls.add("hseparable");}; + if (isVseparable()) { vls.add("vseparable");}; + vls.add(new String("gapCharacter='" + gapCharacter + "'")); + vls.add(new String("returns='" + _genOutputFormatString() + "'")); + return arrayToSeparatorList(vls.toArray(new String[0]), ","); } public String toString() { StringBuffer result = new StringBuffer(); + result.append("|"); result.append(details.Name); result.append('|'); result.append(details.Action); @@ -633,31 +640,63 @@ public class RestServiceDescription return result.toString(); } + /** + * processes a service encoded as a string (as generated by RestServiceDescription.toString()) + * Note - this will only use the first service definition encountered in the string to configure the service. + * @param encoding + * @param warnings - where warning messages are reported. + * @return true if configuration was parsed successfully. + */ public boolean configureFromEncodedString(String encoding, StringBuffer warnings) { - boolean invalid = false; String[] list = separatorListToArray(encoding, "|"); - details.Name = list[0]; - details.Action = list[1]; - details.description = list[2]; - invalid |= !configureFromServiceInputProperties(list[3], warnings); - if (list.length > 5) + + int nextpos=parseServiceList(list,warnings, 0); + if (nextpos>0) { - urlSuffix = list[4]; - invalid |= !configureFromInputParamEncodedUrl(list[5], warnings); + return true; + } + return false; + } + /** + * processes the given list from position p, attempting to configure the service from it. + * Service lists are formed by concatenating individual stringified services. The first character of a stringified service is '|', enabling this, and the parser will ignore empty fields in a '|' separated list when they fall outside a service definition. + * @param list + * @param warnings + * @param p + * @return + */ + protected int parseServiceList(String[] list, StringBuffer warnings, int p) + { + boolean invalid = false; + // look for the first non-empty position - expect it to be service name + while (list[p]!=null && list[p].trim().length()==0) + { + p++; + } + details.Name = list[p]; + details.Action = list[p+1]; + details.description = list[p+2]; + invalid |= !configureFromServiceInputProperties(list[p+3], warnings); + if (list.length-p > 5 && list[p+5]!=null && list[p+5].trim().length()>5) + { + urlSuffix = list[p+4]; + invalid |= !configureFromInputParamEncodedUrl(list[p+5], warnings); + p+=6; } else { - if (list.length > 4) + if (list.length-p > 4 && list[p+4]!=null && list[p+4].trim().length()>5) { urlSuffix = null; - invalid |= !configureFromInputParamEncodedUrl(list[4], warnings); + invalid |= !configureFromInputParamEncodedUrl(list[p+4], warnings); + p+=5; } } - return !invalid; + return invalid ? -1 : p; } - + /** * @return string representation of the input parameters, their type and * constraints, appended to the service's base submission URL @@ -1029,4 +1068,29 @@ public class RestServiceDescription return resultData; } + /** + * parse a concatenated list of rest service descriptions into an array + * @param services + * @return zero or more services. + * @throws exceptions if the services are improperly encoded. + */ + public static List parseDescriptions(String services) throws Exception + { + String[] list = separatorListToArray(services, "|"); + List svcparsed = new ArrayList(); + int p=0,lastp=0; + StringBuffer warnings=new StringBuffer(); + do { + RestServiceDescription rsd = new RestServiceDescription(); + p=rsd.parseServiceList(list, warnings, lastp=p); + if (p>lastp && rsd.isValid()) + { + svcparsed.add(rsd); + } else { + throw new Exception("Failed to parse user defined RSBS services from :"+services+"\nFirst error was encountered at token "+lastp+" starting "+list[lastp]+":\n"+rsd.getInvalidMessage()); + } + } while (p