package jalview.ws2; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import jalview.ws2.operations.Operation; /** * The discoverer and the supplier of the operations/web services available * on the remote hosts. Each web service client used should have it's * implementation of the discoverer acting as an intermediary between the servers * and jalview application. There is no need for more than one discoverer * per web client per application, therefore singletons can be used. * * The discoverer stores a list of url endpoints where the services can be * found and builds instances of {@link jalview.ws2.operations.Operation} * with associated implementations of {@link jalview.ws2.WebServiceI}. * * @author mmwarowny * */ public interface WebServiceDiscovererI { public static final int STATUS_OK = 1; public static final int STATUS_NO_SERVICES = 0; public static final int STATUS_INVALID = -1; public static final int STATUS_UNKNOWN = -2; /** * Get the list of urls that this discoverer will use. */ public List getUrls(); /** * Set the list of urls where this discoverer will search for services. */ public void setUrls(List wsUrls); /** * Test if the url is a valid url for that service discoverer. */ public boolean testUrl(URL url); /** * Get the availability status of the services at the url. Return one of the * status codes {@code STATUS_OK}, {@code STATUS_NO_SERVICES}, * {@code STATUS_INVALID} or {@code STATUS_UNKNOWN}. * * @return status code for the services availability */ public int getStatusForUrl(String url); /** * Get the list of operations found on the servers. * * @return list of operations found */ public List getOperations(); /** * @return whether there are services found */ public boolean hasServices(); /** * Check if service discovery is still in progress. List of operations may be * incomplete when the discoverer is running. * * @return whether the discoverer is running */ public boolean isRunning(); /** * Check if the discoverer is done searching for services. List of operations * should be complete if this methods returns true. * * @return whether the discoverer finished */ public boolean isDone(); /** * Start the service discovery and return a future which will be set with this * discoverer when the process is completed. This method should be called once * on startup and then every time the urls list is updated. * * @return future that will be set on discovery completion */ public CompletableFuture startDiscoverer(); /** * Get the error messages that occurred during service discovery. * * @return error message */ public String getErrorMessages(); /** * An interface for the listeners observing the changes to the operations * list. * * @author mmwarowny */ @FunctionalInterface static interface OperationsChangeListener { /** * Called whenever the operations list of the observed discoverer changes * with that discoverer as the first argument and current operations list as * the second. Operations list can be empty if there are no services or the * list was cleared at the beginning of the discovery. * * @param discoverer * @param list */ public void operationsChanged(WebServiceDiscovererI discoverer, List operations); } List serviceListeners = new CopyOnWriteArrayList<>(); /** * Add an operations list observer that will be notified of any changes. * * @param listener * operations list listener */ public default void addOperationsChangeListener( OperationsChangeListener listener) { serviceListeners.add(listener); } /** * Remove the listener from the observers list. * * @param listener * listener to be removed */ public default void removeOperationsChangeListener( OperationsChangeListener listener) { serviceListeners.remove(listener); } /** * Called whenever the list of operations changes. Notifies all listeners of * the change to the operations list. Typically, should be called with an * empty list at the beginning of the service discovery process and for the * second time with the list of discovered operations after that. * * @param list * new list of discovered operations */ default void fireOperationsChanged(List list) { for (var listener : serviceListeners) { listener.operationsChanged(this, list); } } }