On Thu, Apr 23, 2009 at 11:30, Alan Williams <[email protected]> wrote:
> The filter mechanism currently looks at all the properties of the > service, not just its name. That does mean that it can match services > where the reason for the match is not immediately obvious. The > alternative would be not to match all the "correct" services. What this means, is that if the service provider gives us more information, such as descriptions, etc, it will also search in these. However we have not yet added a general way to show these additional properties, so it might be confusing to get a hit for something, without showing the property that matched the search string. One way to do this is to be inspired by Google and have multiple lines in the results. Obviously this would make the list be longer, so another alternative is to show it in a separate panel, but then you could only see it per selected service. We could do something in the middle of these, were we "expand details" only on the service that has been selected, or if a search is in effect. I'm not sure how easy it is to do this in a JTree though, so we might have to change that as well, meaning that we would have to do such an improvement for 2.2 or as a later update to 2.1. Other things Alan did not mention: You can search for multiple words, Google-style, so for instance typing "gene enzyme" in the search box would match services that have both 'gene' and 'enzyme' in their properties'. You can search by specific properties, but there's no exposure as to what those properties are (basically they are what you previously saw in the drop-down boxes in 2.0), for instance name:gene would match gene only in the getName() property - but not in say getDescription() or getURI(). The APIs for appearing in the service palette are much simplified compared to the old query/partition thing that we didn't quite get to work. Here's an example for Soaplab: http://code.google.com/p/taverna/source/browse/taverna#taverna/ui/net.sf.taverna.t2.ui-activities/trunk/soaplab-activity-ui/src/main/java/net/sf/taverna/t2/activities/soaplab/servicedescriptions%3Fstate%3Dclosed SoaplabServiceProvider.java is the provider of service descriptions, which in this case are instances of the bean SoaplabServiceDescription.java. Think of a service description as a line in the the "Available services" tree, so for most cases it's more on the level of a method than an endpoint. Typically the provider would be configured with an endpoint address, in this case that configuration is in the bean SoaplabServiceProviderConfig.java - so we'll start there: http://code.google.com/p/taverna/source/browse/taverna/ui/net.sf.taverna.t2.ui-activities/trunk/soaplab-activity-ui/src/main/java/net/sf/taverna/t2/activities/soaplab/servicedescriptions/SoaplabServiceProviderConfig.java shows that the configuration of a provider requires only one property, "url". This is normal JavaBean style, so just setBean() and setUrl(). You will notice a little annotation: @PropertyAnnotation(displayName = "Soaplab location", preferred = true) public String getUrl() { return url; } If the configuration bean subclasses net.sf.taverna.t2.lang.beans.PropertyAnnotated - then annotations made using @PropertyAnnotation are provided as normal BeanInfo properties. Alternatively you can make a SoaplabServiceProviderConfigBeanInfo class and provide these manually - but we found that was quite cumbersome, so we made an annotation to do it. You don't need to put in these annotations, any properties will be used by default. The advantage is two things. For the configuration of the service provider, these annotations allow you to give more user friendly "display names" - these are used by the UI builder when creating the "Add Soaplab service" dialogue that pops up when clicking "Add new service". That means that you no longer has to make a little Swing UI just to be added to the tree. We will however make an interface that allows you to specify that yourself if you really want to, for instance BioMoby will need this for a more advanced "Add" dialogue. But in the simple case, where you just need a URI and a few other attributes, the bean itself and some annotations should be enough. Now to the service descriptions themselves. http://code.google.com/p/taverna/source/browse/taverna/ui/net.sf.taverna.t2.ui-activities/trunk/soaplab-activity-ui/src/main/java/net/sf/taverna/t2/activities/soaplab/servicedescriptions/SoaplabServiceDescription.java is a typical service description, note that you will have to subclass ServiceDescription<ConfigType> where ConfigType is the type of the activity configuration. (The one given to theActivity.configure() ). Three bean properties are enforced by this abstract class, getName(), getIcon() and getPath(). The name and icon are what you will see in the service palette. So in theory each method could have a different icon - but in most cases the service providers will just return a static Icon representing their service. getPath() returns a List of String's that says where you want to appear in the service palette tree. So now each service description decides for itself. As a convention, the first folder should be the common for every service from the provider, so in this case it will be a folder called "Soaplab @ http://someurl". In the simplest case, like with WSDLs, this is all you need, so a singleton list with that string can be returned. In the Soaplab case, we also want to expose folders for the categories, so the category (from getCategory() ) is also returned as the second level in the tree. As you see with this, you would no longer have those drop down boxes to select what the tree should be, but the service descriptions themselves decide this. This is no stopper to bring back the 2.0-style of letting the user select how to organize the tree, as all the properties are there, but by default we'll only support the getPath() directly. (Note that the interface states a list of Comparable's - but normally Strings should be used. The idea was that whatever is returned is compared using compareTo() when arranging the tree, and the .toString() is used as the label in the tree. My idea was that you could return say URIs or more clever objects that knew how to arrange themselves - and possibly to add right-clicks later, but I found that the Comparable interface allows the compareTo() method to fail on incompatible objects. So for instance if one service description let's getPath() return Arrays.asList(URI.parse("blasedlasd")); - and another Arrays.asList("Hello") - it's not going to work when sorting them, as URIs refuse to be compared to strings. If you are consistent on deeper-level branches it should still work, though.. but perhaps we should change it to only be a List of String's) OK, so just to finish the service description, we have a few additional methods/properites here: isTemplateService() should always return false - except for template services like Beanshell, RShell etc. In short a template service is one there's only one of, and which needs further configuration (typically poping up a dialogue box) before it really can be used. However, there's a short cut for returning these based on AbstractTemplateProvider getCategory() - which we have already included in the path, getOperation() and getUrl(). Each of these will also be searched overf from the Filter box, and you could search over say only "operation", by saying operation:something You will see that one important job of the service description is to help creating an Activity instance. It does this by providing two items, getActivityClass() returns the *class* of the activity that is to be instantiated (using the public empty constructor), and getActivityConfiguration() returns the configuration bean that is to be applied to the activity, by activity.configure(bean). This will be performed only when the service is added to the workflow, ie. when you drop the service description onto the diagram or the model explorer. OK, so there's lots of these ServiceDescription beans, one per "service", ie. a configuration of an activity that can be added to the workflow. Where do they come from? This is where the service provider comes into the picture. We'll finish with the soaplab provider, it looks like this: http://code.google.com/p/taverna/source/browse/taverna/ui/net.sf.taverna.t2.ui-activities/trunk/soaplab-activity-ui/src/main/java/net/sf/taverna/t2/activities/soaplab/servicedescriptions/SoaplabServiceProvider.java It is extending AbstractConfigurableServiceProvider because it is a so called configurable service provider. In this case it can be configured with a SoaplabServiceProviderConfig - which we saw had the getUri() property - basically the location of the Soaplab installation. To be discovered by Taverna, SoaplabServiceProvider is implementing the SPI net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider, and is therefore listed in: http://code.google.com/p/taverna/source/browse/taverna/ui/net.sf.taverna.t2.ui-activities/trunk/soaplab-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider It has as well getName() and getIcon() - these are used for including the provider in the list you see from the "Add services" button. What happens when you click there, is that a copy will be made of the bean returned through getConfiguration() (in the superclass). This is the *template* configuration bean - and is the one sent in through the constructor: super(new SoaplabServiceProviderConfig("http://somehost/soaplab/services/")); This bean is then used with the automatic UI builder, and it will put up a field for the URI property. Any other properties specified would also be included, but in this case there's just the URI. The defaults will be set from that template bean, so it will say "http://somehost/soaplab/services/" as the initial value. What happens next is that the user edits this string, and clicks "Add". This will then make a *copy* of the SoaplabServiceProviderConfig (using the .clone() method) - and call .configure() on it using the new configuration. This will then be a configured ServiceDescriptionProvider that will be added to the ServiceDescriptionRegistry. The registry will serialize the SoaplabServiceProviderConfig to an XML file in the user's home directory, so that on a restart of Taverna the added service will still be there. (but the endpoint will be queried freshly.) (we could extend this serialisation to actually serialise the whole ServiceDescription beans - this should make Taverna have a list of services immediately at start-up, even without network access. Taverna could then do a refresh in the background to pick up any services that have changed) On adding a new provider to the regisstry, it will call the findServiceDescriptionsAsync() method to get new service descriptions from the providers. These are then put into the registry. One of the listeners to this registry is the "Available services" tree, which will rebuild the tree, using the getPath() etc. from the service descriptions, and put the soaplab services into the tree. You will notice that the findServiceDescriptionsAsync is an asynchronous method with callbacks, it does not simply return the List<ServiceDescription> - as there's no-one waiting for him anymore. The reason for this is that it typically will take some time to do the look-up of services, contacting the WSDL or similar, and we don't want to freeze the UI what that is happening. The provider can call back status reports, like callBack.status("Connecting to Soaplab:" + soaplab); or callBack.warning("oooh") - these are currently shown on a status line in the "Available services" panel. You will see the soaplab provider doing it's soaplab-specific stuff to look up services, and it builds a set of SoaplabServiceDescription beans. It is setting details like category, operation and url. The provider then calls callBack.partialResults(descriptions); with a collection of service descriptions received so far. In the simple cases, like this, it will simply return all results. This will be pushed into the registry, and will almost immediately appear in the tree. For providers that look up several services (like a BioCatalogue or caGrid/caDSR provider), or take a lot of time, they can provide intermediate results, calling partialResults several times. It should then call callback.finished() once it's done. This allows the provider to fill the tree part by part, but for simple services like WSDL we do it all in once, as it would otherwise cause too many UI updates. If anything goes wrong, it can call callBack.fail() - which would present the error message to the user in a dialogue box and remove the service provider from the registry. (including any results given so far). If a RuntimeException happens (like a NullPointerException), a handler on the thread will also catch this and report it using callback.fail(), however this wouldn't provide the user with a usable message. A configurable ServiceDescriptionProvider can also provide a list of ready made provider configurations at getDefaultConfigurations() - the service provider registry will automatically make a new copy of ServiceDescriptionProvider and configure them for each of these default configurations. For example the Soaplab provider includes a bean for the typical soaplab installation at http://www.ebi.ac.uk/soaplab/services/ so that these services will be included in the service palette without a need to click "Add service". However it's debatable if it's clever to provide these hard-coded in the Java, so for our "Bundled WSDLs" we'll probably instead go for a configuration file in the downloaded Taverna distribution - this could just be the same kind of file saved in the users home directory when adding services manually. As you might have guessed, the ServiceDescriptionProvider is not tied with a ServiceDescription - but for a ServiceDescription to appear at least one provider would need to list it. It is possible to build general ServiceDescriptionProvider's that lists different types of service descriptions, some that come to mind: * A BioCatalogue provider * A caDSR provider for caGrid services * A workflow services provider that lists services used in the current (or all) open workflow * My favorites provider -- Stian Soiland-Reyes, myGrid team School of Computer Science The University of Manchester ------------------------------------------------------------------------------ Stay on top of everything new and different, both inside and around Java (TM) technology - register by April 22, and save $200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco. 300 plus technical and hands-on sessions. Register today. Use priority code J9JMT32. http://p.sf.net/sfu/p _______________________________________________ taverna-hackers mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/taverna-hackers Developers Guide: http://www.mygrid.org.uk/usermanual1.7/dev_guide.html FAQ: http://www.mygrid.org.uk/wiki/Mygrid/TavernaFaq
