http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52817a33/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsListingPanel.java ---------------------------------------------------------------------- diff --git a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsListingPanel.java b/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsListingPanel.java deleted file mode 100644 index 2afd190..0000000 --- a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsListingPanel.java +++ /dev/null @@ -1,886 +0,0 @@ -package org.apache.taverna.biocatalogue.ui.search_results; -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Desktop; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.AdjustmentEvent; -import java.awt.event.AdjustmentListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.net.URI; -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JToolBar; -import javax.swing.ListCellRenderer; -import javax.swing.ListModel; -import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; -import javax.swing.event.ListDataListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import org.apache.taverna.biocatalogue.model.BioCataloguePluginConstants; -import org.apache.taverna.biocatalogue.model.LoadingExpandedResource; -import org.apache.taverna.biocatalogue.model.LoadingResource; -import org.apache.taverna.biocatalogue.model.Resource; -import org.apache.taverna.biocatalogue.model.Resource.TYPE; -import org.apache.taverna.biocatalogue.model.ResourceManager; -import org.apache.taverna.biocatalogue.model.Util; -import org.apache.taverna.biocatalogue.model.connectivity.BioCatalogueClient; -import org.apache.taverna.biocatalogue.model.search.SearchInstance; -import org.apache.taverna.biocatalogue.ui.JWaitDialog; -import net.sf.taverna.t2.lang.ui.ModelMap; -import org.apache.taverna.ui.perspectives.biocatalogue.MainComponent; -import org.apache.taverna.ui.perspectives.biocatalogue.MainComponentFactory; -import org.apache.taverna.ui.perspectives.biocatalogue.integration.Integration; -import org.apache.taverna.ui.perspectives.biocatalogue.integration.health_check.ServiceHealthChecker; -import org.apache.taverna.workbench.MainWindow; -import org.apache.taverna.workbench.ModelMapConstants; -import org.apache.taverna.workbench.ui.Workbench; -import org.apache.taverna.workbench.ui.zaria.PerspectiveSPI; - -import org.apache.log4j.Logger; -import org.biocatalogue.x2009.xml.rest.ResourceLink; -import org.biocatalogue.x2009.xml.rest.RestMethod; -import org.biocatalogue.x2009.xml.rest.Service; -import org.biocatalogue.x2009.xml.rest.ServiceTechnologyType; - -/** - * This class is responsible for producing search results listing panel. It only - * shows a single listing for a specified type. Multiple types are handled by - * having different tabs in {@link SearchResultsMainPanel} with instances of - * this class in each. - * - * @author Sergejs Aleksejevs - */ -@SuppressWarnings("serial") -public class SearchResultsListingPanel extends JPanel implements MouseListener, - SearchResultsRenderer, MouseMotionListener { - public static final int SEARCH_STATUS_TOOLTIP_LINE_LENGTH = 65; - - private static final Logger logger = Logger.getLogger(SearchResultsListingPanel.class); - private final SearchResultsMainPanel parentMainSearchResultsPanel; - - // currently displayed search results - SearchInstance searchInstance; - - // main UI components - private SearchResultsListingPanel thisPanel; - private DefaultListModel resultsListingModel; - private JList jlResultsListing; - private JScrollPane spResultsListing; - - // contextual menu - private JPopupMenu contextualMenu; - private Action addToServicePanelAction; - private Action addToWorkflowDiagramAction; - private Action openInBioCatalogueAction; - private Action doHealthCheckAction; - private Action addAllOperationsToServicePanelAction; - - // search status and actions on selected items in the list - private JToolBar tbSelectedItemActions; - protected JPanel jpSearchStatus; - private JLabel jlSearchStatus; - - // this is used for previewing items from the result listing through - // contextual menu - - // value will be updated by mouse event accordingly - private ResourceLink potentialObjectToPreview; - private final TYPE typeToPreview; - - // Design perspective - some actions require switching to it - PerspectiveSPI designPerspective; - - private ListCellRenderer listingCellRenderer; - - /** - * @param typeToPreview - * Resource type that will be previewed in this panel. - * @param parentMainSearchResultsPanel - * Reference to a "parent" of this panel - this is needed to - * notify the main results panel with the - */ - public SearchResultsListingPanel(TYPE typeToPreview, - SearchResultsMainPanel parentMainSearchResultsPanel) { - this.thisPanel = this; - - this.typeToPreview = typeToPreview; - listingCellRenderer = this.typeToPreview - .getResultListingCellRenderer(); - this.parentMainSearchResultsPanel = parentMainSearchResultsPanel; - MainComponentFactory - .getSharedInstance(); - - initialiseUI(); - - this.setPreferredSize(new Dimension(800, 400)); - } - - private void initialiseUI() { - - this.addToServicePanelAction = new AbstractAction( - "Add to Service Panel", - ResourceManager - .getImageIcon(ResourceManager.ADD_PROCESSOR_AS_FAVOURITE_ICON)) { - // Tooltip - { - this.putValue(SHORT_DESCRIPTION, "Add selected " - + typeToPreview.getTypeName() - + " to the Service Panel"); - } - - public void actionPerformed(ActionEvent e) { - final JWaitDialog jwd = new JWaitDialog( - MainComponent.dummyOwnerJFrame, - "Service Catalogue Plugin - Adding " - + typeToPreview.getTypeName(), - "<html><center>Please wait for selected " - + typeToPreview.getTypeName() - + " details to be fetched from the Service Catalogue<br>" - + "and to be added into the Service Panel.</center></html>"); - - new Thread("Adding " + typeToPreview.getTypeName() - + " into Service Panel") { - public void run() { - // if it is the expanded that we are looking at, need to extract - // the 'associated' object - ResourceLink processorResourceToAdd = (potentialObjectToPreview instanceof LoadingExpandedResource ? ((LoadingExpandedResource) potentialObjectToPreview) - .getAssociatedObj() - : potentialObjectToPreview); - - JComponent insertionOutcome = Integration - .insertProcesorIntoServicePanel(processorResourceToAdd); - jwd.waitFinished(insertionOutcome); - - // Switch to Design Perspective - switchToDesignPerspective(); - } - }.start(); - - // NB! The modal dialog window needs to be made visible after - // the background - // process (i.e. adding a processor) has already been started! - jwd.setVisible(true); - } - }; - - // For a parent Web service, action to add all operations to the Service Panel. - // Works for SOAP services at the moment. - this.addAllOperationsToServicePanelAction = new AbstractAction( - "Add all operations to Service Panel", - ResourceManager - .getImageIcon(ResourceManager.ADD_ALL_SERVICES_AS_FAVOURITE_ICON)) { - // Tooltip - { - this.putValue(SHORT_DESCRIPTION, "Add all associated services to the Service Panel"); - } - - public void actionPerformed(ActionEvent e) { - final JWaitDialog jwd = new JWaitDialog( - MainComponent.dummyOwnerJFrame, - "Service Catalogue Plugin - Adding " - + typeToPreview.getTypeName(), - "<html><center>Please wait for selected " - + typeToPreview.getTypeName() - + " details to be fetched from the Service Catalogue<br>" - + "and to be added into the Service Panel.</center></html>"); - - new Thread("Adding all operations of " + typeToPreview.getTypeName() - + " to the Service Panel") { - public void run() { - // if it is the expanded that we are looking at, need to extract - // the 'associated' object - ResourceLink resourceLink = (potentialObjectToPreview instanceof LoadingExpandedResource ? ((LoadingExpandedResource) potentialObjectToPreview) - .getAssociatedObj() - : potentialObjectToPreview); - - JComponent insertionOutcome = Integration - .insertAllOperationsIntoServicePanel(resourceLink); - jwd.waitFinished(insertionOutcome); - - // Switch to Design Perspective - switchToDesignPerspective(); - } - }.start(); - - // NB! The modal dialog window needs to be made visible after - // the background - // process (i.e. adding a processor) has already been started! - jwd.setVisible(true); - } - }; - - this.addToWorkflowDiagramAction = new AbstractAction( - "Add to workflow", - ResourceManager - .getImageIcon(ResourceManager.ADD_PROCESSOR_TO_WORKFLOW_ICON)) { - // Tooltip - { - this.putValue(SHORT_DESCRIPTION, "<html>Insert selected " - + typeToPreview.getTypeName() - + " into the current workflow</html>"); - } - - public void actionPerformed(ActionEvent e) { - final JWaitDialog jwd = new JWaitDialog( - MainComponent.dummyOwnerJFrame, - "Service Catalogue Plugin - Adding " - + typeToPreview.getTypeName(), - "<html><center>Please wait for selected " - + typeToPreview.getTypeName() - + " details to be fetched from the Service Catalogue<br>" - + "and to be added into the current workflow.</center></html>"); - - new Thread("Adding " + typeToPreview.getTypeName() - + " into workflow") { - public void run() { - // if it is the expanded that we are looking at, need to extract - // the 'associated' object - ResourceLink processorResourceToAdd = (potentialObjectToPreview instanceof LoadingExpandedResource ? ((LoadingExpandedResource) potentialObjectToPreview) - .getAssociatedObj() - : potentialObjectToPreview); - - JComponent insertionOutcome = Integration - .insertProcessorIntoCurrentWorkflow(processorResourceToAdd); - jwd.waitFinished(insertionOutcome); - - // Switch to Design Perspective - switchToDesignPerspective(); - } - }.start(); - - // NB! The modal dialog window needs to be made visible after - // the background - // process (i.e. adding a processor) has already been started! - jwd.setVisible(true); - } - }; - - this.openInBioCatalogueAction = new AbstractAction( - "Open in the Service Catalogue", - ResourceManager - .getImageIcon(ResourceManager.OPEN_IN_BIOCATALOGUE_ICON)) { - // Tooltip - { - this.putValue(SHORT_DESCRIPTION, "<html>View selected " - + typeToPreview.getTypeName() - + " on the Service Catalogue Web site.<br>" - + "This will open your standard Web browser.</html>"); - } - - public void actionPerformed(ActionEvent e) { - String hrefString = potentialObjectToPreview.getHref(); - try { - Desktop.getDesktop().browse(new URI(hrefString)); - } - catch (Exception ex) { - logger.error("Failed while trying to open the URL in a standard browser; URL was: " + - hrefString + "\nException was: " + ex + "\n" + ex.getStackTrace()); - }; - } - }; - - this.doHealthCheckAction = new AbstractAction( - "Check monitoring status", - ResourceManager - .getImageIcon(ResourceManager.EXECUTE_HEALTH_CHECK_ICON)) { - // Tooltip - { - this - .putValue( - SHORT_DESCRIPTION, - "<html>Fetch the latest monitoring data for selected " - + typeToPreview.getTypeName() - + ".<br>" - + "Data will be obtained from the Service Catalogue and displayed in a popup window.</html>"); - } - - public void actionPerformed(ActionEvent e) { - // if it is the expanded that we are looking at, need to extract - // the 'associated' object - ResourceLink resourceForHealthCheck = (potentialObjectToPreview instanceof LoadingExpandedResource ? ((LoadingExpandedResource) potentialObjectToPreview) - .getAssociatedObj() - : potentialObjectToPreview); - - ServiceHealthChecker.checkResource(resourceForHealthCheck); - } - }; - - tbSelectedItemActions = new JToolBar(JToolBar.HORIZONTAL); - tbSelectedItemActions.setBorderPainted(true); - tbSelectedItemActions.setBorder(BorderFactory.createEmptyBorder(5, 5, - 5, 3)); - tbSelectedItemActions.setFloatable(false); - if (typeToPreview.isSuitableForAddingToServicePanel()) { - tbSelectedItemActions.add(addToServicePanelAction); - } - if (typeToPreview.isSuitableForAddingAllToServicePanel()) { - tbSelectedItemActions.add(addAllOperationsToServicePanelAction); - } - if (typeToPreview.isSuitableForAddingToWorkflowDiagram()) { - tbSelectedItemActions.add(addToWorkflowDiagramAction); - } - if (typeToPreview.isSuitableForHealthCheck()) { - tbSelectedItemActions.add(doHealthCheckAction); - } - tbSelectedItemActions.add(openInBioCatalogueAction); - - // *** Prepare search results status panel *** - - GridBagConstraints c = new GridBagConstraints(); - jpSearchStatus = new JPanel(new GridBagLayout()); - c.anchor = GridBagConstraints.WEST; - c.weightx = 0; - jpSearchStatus.add(tbSelectedItemActions, c); - - jlSearchStatus = new JLabel(); - jlSearchStatus.setIconTextGap(20); - c.weightx = 1.0; - c.insets = new Insets(0, 20, 0, 0); - jpSearchStatus.add(jlSearchStatus, c); - - if (parentMainSearchResultsPanel.getFilterTreePaneFor(typeToPreview) != null) { - Dimension preferredSize = new Dimension(200, - parentMainSearchResultsPanel.getFilterTreePaneFor( - typeToPreview).getTreeToolbarPreferredSize().height); - - // HACK: due to concurrency issues, sometimes this doesn't work - // correctly - - // to rectify the problem using the hard-coded value that was - // correct at - // the time of coding... - if (preferredSize.height < 30) { - preferredSize.height = 33; - } - - jpSearchStatus.setPreferredSize(preferredSize); - } - - // *** Create list to hold search results and wrap it into a scroll pane - // *** - resultsListingModel = new DefaultListModel(); - jlResultsListing = new JList(resultsListingModel); - jlResultsListing.setDoubleBuffered(true); - jlResultsListing.setCellRenderer(listingCellRenderer); - jlResultsListing.addMouseListener(this); - jlResultsListing.addMouseMotionListener(this); - jlResultsListing.setBackground(thisPanel.getBackground()); - - jlResultsListing.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - jlResultsListing.addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting()) { - // update value to be used in contextual menu click handler - // to act on the just-selected entry - potentialObjectToPreview = getResourceSelectedInJList(); - - if (potentialObjectToPreview != null) { - - // only enable actions in the menu if the list entry - // that is being - // clicked on is beyond the initial 'loading' state - boolean shown = !isListEntryOnlyWithInitialDetails(potentialObjectToPreview); - boolean shownAndNotArchived = shown && !isArchived(potentialObjectToPreview); - addToServicePanelAction - .setEnabled(shownAndNotArchived); - addAllOperationsToServicePanelAction - .setEnabled(shownAndNotArchived && !(potentialObjectToPreview instanceof RestMethod)); - addToWorkflowDiagramAction - .setEnabled(shownAndNotArchived); - openInBioCatalogueAction - .setEnabled(shown); - doHealthCheckAction - .setEnabled(shown); - - return; - } - } - - // disable actions if nothing is selected in the list or if - // selection is still "adjusting" - addToServicePanelAction.setEnabled(false); - addAllOperationsToServicePanelAction.setEnabled(false); - addToWorkflowDiagramAction.setEnabled(false); - openInBioCatalogueAction.setEnabled(false); - doHealthCheckAction.setEnabled(false); - } - }); - - spResultsListing = new JScrollPane(jlResultsListing); - spResultsListing.getVerticalScrollBar().addAdjustmentListener( - new AdjustmentListener() { - public void adjustmentValueChanged(AdjustmentEvent e) { - if (!e.getValueIsAdjusting()) { - // load missing details on adjusting the scroll bar - // - // only start loading more results in case if the - // value is "not adjusting" - - // this means that the mouse has been released and - // is not dragging the scroll bar - // any more, so effectively the user has stopped - // scrolling - checkAllEntriesInTheVisiblePartOfJListAreLoaded(); - } - } - }); - - // tie components to the class panel itself - this.resetSearchResultsListing(true); - - // *** Create CONTEXTUAL MENU *** - - contextualMenu = new JPopupMenu(); - if (typeToPreview.isSuitableForAddingToServicePanel()) { - contextualMenu.add(addToServicePanelAction); - contextualMenu.add(addAllOperationsToServicePanelAction); - } - if (typeToPreview.isSuitableForAddingToWorkflowDiagram()) { - contextualMenu.add(addToWorkflowDiagramAction); - } - if (typeToPreview.isSuitableForHealthCheck()) { - contextualMenu.add(doHealthCheckAction); - } - contextualMenu.add(openInBioCatalogueAction); - } - - /** - * Allows to set the search status by supplying the message to display. - */ - protected void setSearchStatusText(final String statusString, - final boolean spinnerActive) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - jlSearchStatus - .setIcon(spinnerActive ? ResourceManager - .getImageIcon(ResourceManager.BAR_LOADER_ORANGE) - : null); - - jlSearchStatus.setText(statusString); - jlSearchStatus.setToolTipText("<html>" - + Util.ensureLineLengthWithinString(statusString, - SEARCH_STATUS_TOOLTIP_LINE_LENGTH, false) - + "</html>"); - } - }); - } - - /** - * This helper method is used to initialise this panel. Also invoked when - * search results need to be cleared. - * - * @param showSuggestion - * <code>true</code> should be used on first load of the panel - - * in that case a suggestion would be displayed to perform a - * search, tag search or start directly with filtering;<br/> - * <code>false</code> to be used when resetting the panel after - * perfoming the search, but not finding any results. - */ - public void resetSearchResultsListing(boolean showSuggestion) { - setSearchStatusText("No searches were made yet", false); - - String labelText = "<html><center>" - + (showSuggestion ? "You can find " - + this.typeToPreview.getCollectionName() - + " by typing a search query." - + (this.typeToPreview.isSuitableForFiltering() ? "<br><br>Alternatively, you can select some filters from the tree on the left." - : "") - : "There are no " - + this.typeToPreview.getCollectionName() - + " that match your search criteria<br><br>" - + "Please try making the search query shorter or selecting fewer filters") - + "</center></html>"; - - JLabel jlMainLabel = new JLabel(labelText, JLabel.CENTER); - jlMainLabel.setFont(jlMainLabel.getFont().deriveFont(Font.PLAIN, 16)); - jlMainLabel.setBorder(BorderFactory.createEtchedBorder()); - - this.removeAll(); - this.setLayout(new BorderLayout(0, 0)); - this.add(jpSearchStatus, BorderLayout.NORTH); - this.add(jlMainLabel, BorderLayout.CENTER); - this.validate(); - - // disable the toolbar actions - this.addToServicePanelAction.setEnabled(false); - this.addToWorkflowDiagramAction.setEnabled(false); - this.openInBioCatalogueAction.setEnabled(false); - this.doHealthCheckAction.setEnabled(false); - this.addAllOperationsToServicePanelAction.setEnabled(false); - } - - /** - * Statistics will be rendered along with the collection of found items. - * - * @param searchInstance - * SearchInstance containing search results to render. - */ - public void renderResults(SearchInstance searchInstance) { - // make the current search instance available globally within this class - this.searchInstance = searchInstance; - - // stop spinner icon on the tab that is populated and add number of - // results - parentMainSearchResultsPanel.setDefaultIconForTab(typeToPreview); - parentMainSearchResultsPanel.setDefaultTitleForTabWithSuffix( - typeToPreview, " (" - + searchInstance.getSearchResults() - .getTotalMatchingItemCount() + ")"); - - // if nothing was found - display notification and finish result - // processing - if (searchInstance.getSearchResults().getTotalMatchingItemCount() == 0) { - resetSearchResultsListing(false); - - // must happen after resetting the listing, as it replaces the - // default status text - setSearchStatusText("No results found for " - + searchInstance.getDescriptionStringForSearchStatus(), - false); - return; - } - - // populate results - if (searchInstance.getSearchResults().getTotalMatchingItemCount() > 0) { - // populate the list box with users - - List<? extends ResourceLink> foundItems = searchInstance - .getSearchResults().getFoundItems(); - for (ResourceLink item : foundItems) { - resultsListingModel.addElement(item); - } - } - - // update the UI once contents are ready - thisPanel.removeAll(); - thisPanel.setLayout(new BorderLayout(0, 0)); - thisPanel.add(jpSearchStatus, BorderLayout.NORTH); - thisPanel.add(spResultsListing, BorderLayout.CENTER); - thisPanel.repaint(); - - // automatically start loading details for the first section of result - // listing - SwingUtilities.invokeLater(new Runnable() { - public void run() { - checkAllEntriesInTheVisiblePartOfJListAreLoaded(); - } - }); - - // *** Also update status text *** - - setSearchStatusText("Search results for " - + searchInstance.getDescriptionStringForSearchStatus(), false); - } - - /** - * Check if details are fetched for all result entries that are currently - * visible in the JList. - * - * If some are not yet loaded, identifies the page in the index of - * corresponding resources to fetch details. - * - * When done, recursively calls itself again to verify that no more entries - * need further details loaded. - */ - private void checkAllEntriesInTheVisiblePartOfJListAreLoaded() { - int firstVisibleIndex = jlResultsListing.getFirstVisibleIndex(); - - if (firstVisibleIndex >= 0) { - int lastVisibleIndex = jlResultsListing.getLastVisibleIndex(); - - final int firstNotFetchedMatchingItemIndex = searchInstance - .getSearchResults().getFirstMatchingItemIndexNotYetFetched( - firstVisibleIndex, lastVisibleIndex); - final int pageToFetchNumber = searchInstance.getSearchResults() - .getMatchingItemPageNumberFor( - firstNotFetchedMatchingItemIndex); - - // check if found a valid page to load - if (pageToFetchNumber != -1) { - int numberOfResourcesPerPageForThisResourceType = searchInstance - .getSearchResults().getTypeOfResourcesInTheResultSet() - .getApiResourceCountPerIndexPage(); - - int firstListIndexToLoad = searchInstance.getSearchResults() - .getFirstItemIndexOn(pageToFetchNumber); // first - // element - // on the - // page that - // is about - // to be - // loaded - int countToLoad = Math.min( - numberOfResourcesPerPageForThisResourceType, // if the - // last - // page - // isn't - // full, - // need - // to - // mark - // less - // items - // than - // the - // full - // page - resultsListingModel.getSize() - firstListIndexToLoad); - - // mark the next "page" of items in the JList as "loading" - - // but also mark them in the SearchResults backing list, so - // that next calls to this listener are aware of the previous - // items that were marked as "loading" - for (int i = firstListIndexToLoad; i < firstListIndexToLoad - + countToLoad; i++) { - ((LoadingResource) searchInstance.getSearchResults() - .getFoundItems().get(i)).setLoading(true); - } - - // update the UI to show 'loading' state on relevant entries - renderFurtherResults(searchInstance, firstListIndexToLoad, - countToLoad); - - // now start loading data for the 'loading' entries - final CountDownLatch latch = new CountDownLatch(1); - new Thread("Search via the API") { - public void run() { - try { - searchInstance.fetchMoreResults( - parentMainSearchResultsPanel, latch, - thisPanel, pageToFetchNumber); - } catch (Exception e) { - logger.error("Error while searching via the Service Catalogue API", e); - - } - } - }.start(); - - // wait for the previous portion of results to load, then fetch - // the next portion - new Thread( - "Fetch more another page of details for search results") { - public void run() { - try { - latch.await(); - checkAllEntriesInTheVisiblePartOfJListAreLoaded(); - } catch (InterruptedException e) { - logger - .error( - "Failed to wait for the previous page of results to load to check if " - + "another one needs loading as well. Details in the attache exception.", - e); - } - } - }.start(); - - } - } - } - - /** - * Tests whether {@link ResourceLink} object corresponding to an entry in - * the search results list is in the state where only the first (initial) - * fragment of data was loaded (through BioCatalogue LITE JSON API) that - * contains just the title + URL of the resource. - * - * @param resource - * @return - */ - private boolean isListEntryOnlyWithInitialDetails(ResourceLink resource) { - return (resource instanceof LoadingResource); - } - - private boolean isArchived(ResourceLink resource) { - if (listingCellRenderer instanceof ExpandableOnDemandLoadedListCellRenderer) { - ExpandableOnDemandLoadedListCellRenderer r = (ExpandableOnDemandLoadedListCellRenderer) listingCellRenderer; - return r.shouldBeHidden(resource); - } - return false; - } - - - // ***** Callbacks for MouseListener ***** - - public void mouseClicked(MouseEvent e) { - } - - public void mouseEntered(MouseEvent e) { /* NOT IN USE */ - } - - public void mouseExited(MouseEvent e) { /* NOT IN USE */ - } - - public void mousePressed(MouseEvent e) { - // checked in both mousePressed() & mouseReleased() for cross-platform - // operation - maybeShowPopupMenu(e); - } - - public void mouseReleased(MouseEvent e) { - // checked in both mousePressed() & mouseReleased() for cross-platform - // operation - maybeShowPopupMenu(e); - } - - // ***** Callbacks for MouseMotionListener ***** - - public void mouseMoved(MouseEvent e) { - } - - public void mouseDragged(MouseEvent e) { /* do nothing */ - } - - /** - * Gets the selected object from the specified list. Used for previewing - * items through double-clicks and contextual menu. - * - * @return <code>null</code> if no selection in the list, - * <code>ResourceLink</code> object that is currently selected - * otherwise. - */ - private ResourceLink getResourceSelectedInJList() { - return (jlResultsListing.getSelectedIndex() == -1 ? null - : (ResourceLink) jlResultsListing.getSelectedValue()); - } - - private void maybeShowPopupMenu(MouseEvent e) { - if (e.getSource().equals(jlResultsListing) && e.isPopupTrigger() - && jlResultsListing.locationToIndex(e.getPoint()) != -1) { - // select the entry in the list that triggered the event to show - // this popup menu - jlResultsListing.setSelectedIndex(jlResultsListing - .locationToIndex(e.getPoint())); - - // update value to be used in contextual menu click handler to act - // on the just-selected entry - potentialObjectToPreview = getResourceSelectedInJList(); - - // show the contextual menu - this.contextualMenu.show(e.getComponent(), e.getX(), e.getY()); - } - } - - // *** Callbacks for SearchResultsRenderer *** - - public void renderInitialResults(final SearchInstance si) { - // NB! critical to have UI update done within the invokeLater() - // method - this is to prevent UI from 'flashing' and to - // avoid concurrency-related errors - SwingUtilities.invokeLater(new Runnable() { - public void run() { - // make sure to remove any old results from the list model! - resultsListingModel.clear(); - - // display the partial search results - logger.debug("Started rendering initial search results for " - + si.getResourceTypeToSearchFor().getCollectionName()); - renderResults(si); - logger.debug("Finished rendering initial search results for " - + si.getResourceTypeToSearchFor().getCollectionName()); - } - }); - } - - public void renderFurtherResults(SearchInstance si, int startIndex, - int count) { - renderFurtherResults(si, startIndex, count, false); - } - - public void renderFurtherResults(final SearchInstance si, - final int startIndex, final int count, - final boolean disableListDataListeners) { - logger.debug("Started rendering further search results for " - + si.getResourceTypeToSearchFor().getCollectionName()); - - // NB! very important to remove all listeners here, so that the JList - // won't "freeze" - // on updating the components - ListDataListener[] listeners = null; - if (disableListDataListeners) { - listeners = resultsListingModel.getListDataListeners(); - for (ListDataListener listener : listeners) { - resultsListingModel.removeListDataListener(listener); - } - } - - for (int i = startIndex; i < startIndex + count - && i < resultsListingModel.getSize(); i++) { - resultsListingModel.set(i, searchInstance.getSearchResults() - .getFoundItems().get(i)); - } - - // reset all listeners in case they were removed - if (disableListDataListeners) { - for (ListDataListener listener : listeners) { - resultsListingModel.addListDataListener(listener); - } - } - - // NB! critical to have UI update done within the invokeLater() - // method - this is to prevent UI from 'flashing' and to - // avoid some weird errors - SwingUtilities.invokeLater(new Runnable() { - public void run() { - jlResultsListing.validate(); - jlResultsListing.repaint(); - - logger.debug("Finished rendering further search results for " - + si.getResourceTypeToSearchFor().getCollectionName()); - } - }); - } - - private void switchToDesignPerspective() { - if (designPerspective == null) { - for (PerspectiveSPI perspective : Workbench.getInstance() - .getPerspectives().getPerspectives()) { - if (perspective.getText().equalsIgnoreCase("design")) { - designPerspective = perspective; - break; - } - } - } - - if (designPerspective != null) { - ModelMap.getInstance().setModel( - ModelMapConstants.CURRENT_PERSPECTIVE, designPerspective); - } - } -}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52817a33/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsMainPanel.java ---------------------------------------------------------------------- diff --git a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsMainPanel.java b/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsMainPanel.java deleted file mode 100644 index 03455f2..0000000 --- a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsMainPanel.java +++ /dev/null @@ -1,514 +0,0 @@ -package org.apache.taverna.biocatalogue.ui.search_results; -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.CountDownLatch; - -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JToggleButton; - -import org.apache.taverna.biocatalogue.model.ResourceManager; -import org.apache.taverna.biocatalogue.model.Resource.TYPE; -import org.apache.taverna.biocatalogue.model.search.SearchInstance; -import org.apache.taverna.biocatalogue.model.search.SearchInstanceTracker; -import org.apache.taverna.biocatalogue.model.search.SearchOptions; -import org.apache.taverna.biocatalogue.model.search.ServiceFilteringSettings; -import org.apache.taverna.biocatalogue.ui.filtertree.FilterTreePane; -import org.apache.taverna.ui.perspectives.biocatalogue.MainComponentFactory; - -import org.apache.log4j.Logger; - -/** - * This class represents the main panel that deals with the status - * and results of the current search. - * - * It has a status label, spinner to depict search in progress, - * actual search results split into tabs by their type, a toolbar - * with search history, favourite searches settings, favourite filters, - * ability to restart last search, etc. - * - * @author Sergejs Aleksejevs - */ -public class SearchResultsMainPanel extends JPanel implements ActionListener, SearchInstanceTracker -{ - private final SearchResultsMainPanel instanceOfSelf; - private Logger logger; - - private LinkedHashMap<TYPE, JComponent> searchResultTabs; - private Map<TYPE, SearchResultsListingPanel> searchResultListings; - - // holds a reference to the instance of the search instances in the current context - // that should be active at the moment (will aid early termination of older searches - // when new ones are started) - private Map<TYPE, SearchInstance> currentSearchInstances; - - // holds a map of references to the current instances of filter trees per resource type - private Map<TYPE, FilterTreePane> currentFilterPanes; - - - // COMPONENTS - private JTabbedPane tabbedSearchResultPanel; - - protected JToggleButton bToggleSearchHistory; - protected JButton bRefreshLastSearch; - protected JButton bClearSearchResults; - - - public SearchResultsMainPanel() - { - this.instanceOfSelf = this; - MainComponentFactory.getSharedInstance(); - this.logger = Logger.getLogger(SearchResultsMainPanel.class); - - this.currentSearchInstances = new HashMap<TYPE,SearchInstance>(); - - this.searchResultListings = new HashMap<TYPE, SearchResultsListingPanel>(); - this.currentFilterPanes = new HashMap<TYPE,FilterTreePane>(); - this.searchResultTabs = new LinkedHashMap<TYPE, JComponent>(); // crucial to preserve the order -- so that these tabs always appear in the UI in the same order! - initialiseResultTabsMap(); - - initialiseUI(); - } - - - private void initialiseUI() - { - // create a panel for tabbed listings of search results - this.tabbedSearchResultPanel = new JTabbedPane(); - reloadResultTabsFromMap(); - - // pack all main components together - JPanel jpMainResultsPanel = new JPanel(new BorderLayout()); - jpMainResultsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 3)); - - jpMainResultsPanel.add(tabbedSearchResultPanel, BorderLayout.CENTER); - - - // --- Put together all parts --- - // main components in the middle, toolbar on the right - this.setMinimumSize(new Dimension(450, 50)); - this.setLayout(new BorderLayout()); - this.add(jpMainResultsPanel, BorderLayout.CENTER); - - // FIXME - add toolbar to the main window! -// this.add(tbSearchActions, BorderLayout.EAST); - } - - - - // ----- Hiding / Showing tabs for various search result types ----- - - /** - * Dynamically populates the map of resource types and components that represent these types - * in the tabbed pane -- this is only to be done once during the initialisation. - */ - private void initialiseResultTabsMap() - { - for (TYPE t : TYPE.values()) { - toggleResultTabsInMap(t, t.isDefaultSearchType()); - } - } - - - /** - * Adds or removes a tab for a specified type of resource. - * - * @param type Resource type for which the tab is to be added / removed. - * @param doShowTab Defines whether to add or remove tab for this resource type. - */ - public void toggleResultTabsInMap(TYPE type, boolean doShowTab) - { - JPanel jpResultTabContent = null; - - if (doShowTab) - { - jpResultTabContent = new JPanel(new GridLayout()); - - // decide if this resource type supports filtering - if (type.isSuitableForFiltering()) { - FilterTreePane filterTreePane = new FilterTreePane(type); - this.currentFilterPanes.put(type, filterTreePane); - } - else { - // not suitable for filtering - record this in a map - this.currentFilterPanes.put(type, null); - } - - - SearchResultsListingPanel resultsListingPanel = new SearchResultsListingPanel(type, this); - this.searchResultListings.put(type, resultsListingPanel); - - if (this.currentFilterPanes.get(type) == null) { - jpResultTabContent.add(resultsListingPanel); - } - else { - JSplitPane spFiltersAndResultListing = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - spFiltersAndResultListing.setLeftComponent(this.currentFilterPanes.get(type)); - spFiltersAndResultListing.setRightComponent(resultsListingPanel); - jpResultTabContent.add(spFiltersAndResultListing); - } - } - else { - // tab for this type is being hidden - just remove the references - // to the search result listing and to filter pane - this.searchResultListings.put(type, null); - this.currentFilterPanes.put(type, null); - } - - this.searchResultTabs.put(type, jpResultTabContent); - } - - - /** - * (Re-)loads the user interface from the internal map. - */ - public void reloadResultTabsFromMap() - { - Component selectedTabsComponent = tabbedSearchResultPanel.getSelectedComponent(); - tabbedSearchResultPanel.removeAll(); - for (TYPE type : this.searchResultTabs.keySet()) { - JComponent c = this.searchResultTabs.get(type); - if (c != null) { - tabbedSearchResultPanel.addTab(type.getCollectionName(), type.getIcon(), c, type.getCollectionTabTooltip()); - } - } - - // attempt to re-select the same tab that was open before reloading - try { - tabbedSearchResultPanel.setSelectedComponent(selectedTabsComponent); - } - catch (IllegalArgumentException e) { - // failed - probably previously selected tab got removed - select the first one - tabbedSearchResultPanel.setSelectedIndex(0); - } - } - - - /** - * @param resourceType Resource type to look for. - * @return Current index of the tab in the results tabbed pane view - * that holds a component showing search results for this type. - * Returns <code>-1</code> if requested type is not currently displayed. - */ - protected int getTabIndexForResourceType(TYPE resourceType) { - return (tabbedSearchResultPanel.indexOfComponent(searchResultTabs.get(resourceType))); - } - - - // ----- ------ - - - /** - * This method is intended to be called when filter options in one of the tabs change. - * It starts the new filtering operation. - * - * Effectively it sets the filtering parameters for the SearchInstance - * and then starts a new search with that {@link SearchInstance} wrapped into {@link SearchOptions}. - * - * @param resourceType Resource type for which the new filtering operation is started - * @param filteringSettings Filtering settings for the current filtering operation - * obtained from the filter tree (or favourite filters). - */ - public void startNewFiltering(TYPE resourceType, ServiceFilteringSettings filteringSettings) - { - SearchInstance siPreviousSearchForThisType = getCurrentSearchInstance(resourceType); - - // pass on the filtering parameters to the relevant search instance (this will overwrite the old ones if any were present!) - if (siPreviousSearchForThisType == null) { - // no filterings have been done earlier for this resource type; - // we'll need a new (blank) query search SearchInstance and - // wrap it into a service filtering SearchInstance - siPreviousSearchForThisType = new SearchInstance(new SearchInstance("", resourceType), filteringSettings); - } - else { - if (!siPreviousSearchForThisType.isServiceFilteringSearch()) { - // just wrap existing search instance that was (probably) transferred from the Search tab - // into another SearchInstance that explicitly deals with service filtering - siPreviousSearchForThisType = new SearchInstance(siPreviousSearchForThisType, filteringSettings); - } - else { - // previous search instance dealt with filtering - - // simply update the filtering settings (but before that - // run a 'deep copy' of the original search instance, so - // that the new one gets a new reference; this will aid - // in early termination of older filterings) - siPreviousSearchForThisType = siPreviousSearchForThisType.deepCopy(); - siPreviousSearchForThisType.setFilteringSettings(filteringSettings); - } - } - - // proceed with "search" as usual - it will treat this search instance differently - // from "ordinary" search - startNewSearch(new SearchOptions(siPreviousSearchForThisType)); - } - - - /** - * Worker method responsible for starting a new search via the API. - * - * This method is to be used when a *new* search is started. It will - * mainly make updates to the UI and store the new search in the history. - */ - public void startNewSearch(final SearchOptions searchOptions) - { - try - { - for (final TYPE resourceType : searchOptions.getResourceTypesToSearchFor()) - { - SearchInstance si = null; - switch (searchOptions.getSearchType()) { - case QuerySearch: si = new SearchInstance(searchOptions.getSearchString(), resourceType); - resetAllFilterPanes(searchOptions.getSearchString()); - break; - - case TagSearch: if (resourceType.isSuitableForTagSearch()) { - si = new SearchInstance(searchOptions.getSearchTags(), resourceType); - resetAllFilterPanes(searchOptions.getSearchString()); - } - else { - // FIXME implement this... - show "no results" in the appropriate tab - JOptionPane.showMessageDialog(null, "'" + resourceType.getTypeName() + "' resource type is not suitable for tag search"); - } - break; - - case Filtering: if (resourceType.isSuitableForFiltering()) { - si = searchOptions.getPreconfiguredSearchInstance(); - } - else { - // FIXME implement this... - show "no results" in the appropriate tab - JOptionPane.showMessageDialog(null, "'" + resourceType.getTypeName() + "' resource type is not suitable for filtering"); - } - break; - } - - if (si.isEmptySearch()) { - clearListingPanels(); - return; - } - - // Record 'this' search instance and set it as the new "primary" one for - // this resource type; - // (this way it if a new search thread starts afterwards, it is possible to - // detect this and stop the 'older' search, because it is no longer relevant) - registerSearchInstance(resourceType, si); - - // start spinner icon for this tab to indicate search in progress - also show status message - setSpinnerIconForTab(resourceType); - setDefaultTitleForTab(resourceType); - searchResultListings.get(resourceType).setSearchStatusText("Searching for " + si.getDescriptionStringForSearchStatus() + "...", true); - - - // start the actual search - final SearchInstance siToStart = si; - new Thread(searchOptions.getSearchType() + " of " + resourceType.getCollectionName() + " via the API") { - public void run() { - siToStart.startNewSearch(instanceOfSelf, new CountDownLatch(1), searchResultListings.get(resourceType)); // FIXME - the new countdown latch is never used... - } - }.start(); - } - } - catch (Exception e) { - logger.error("Error while searching via the Service Catalogue API. Error details attached.", e); - } - -} - - - - /** - * Clears selection of filtering criteria and collapses any expanded nodes - * in all filter tree panes.<br/><br/> - * - * To be used for resetting all filter panes when the new query / tag - * search starts. - * @param queryString - */ - private void resetAllFilterPanes(String queryString) { - for (FilterTreePane filterTreePane : this.currentFilterPanes.values()) { - if (filterTreePane != null) { - filterTreePane.clearSelection(); - filterTreePane.collapseAll(); - if ((queryString != null) && !queryString.isEmpty()) { - filterTreePane.applyQueryString(queryString); - } - } - } - } - - - protected void setSpinnerIconForTab(TYPE resourceType) { - tabbedSearchResultPanel.setIconAt(getTabIndexForResourceType(resourceType), ResourceManager.getImageIcon(ResourceManager.SPINNER)); - } - - protected void setDefaultIconForTab(TYPE resourceType) { - this.tabbedSearchResultPanel.setIconAt(getTabIndexForResourceType(resourceType), resourceType.getIcon()); - } - - - /** - * Same as {@link SearchResultsMainPanel#setDefaultTitleForTab(TYPE)}, - * but allows to append a specified string at the end of the default title. - * - * @param resourceType - * @param suffix - */ - protected void setDefaultTitleForTabWithSuffix(TYPE resourceType, String suffix) { - tabbedSearchResultPanel.setTitleAt(getTabIndexForResourceType(resourceType), - resourceType.getCollectionName() + (suffix == null ? "" : suffix) ); - } - - - /** - * Sets default title for a tab that contains panel representing - * search results of the specified resource type. Default title - * is just a name of the collections of resources in that tab. - * - * @param resourceType - */ - protected void setDefaultTitleForTab(TYPE resourceType) { - setDefaultTitleForTabWithSuffix(resourceType, null); - } - - - /** - * @param resourceType Resource type for which the search result listing panel is requested. - * @return Reference to the requested panel or <code>null</code> if a tab for the specified - * <code>resourceType</code> does not exist. - */ - protected SearchResultsListingPanel getResultsListingFor(TYPE resourceType) { - return (this.searchResultListings.get(resourceType)); - } - - - /** - * @param resourceType Resource type for which filter tree pane is to be returned. - * @return Reference to the requested filter tree pane or <code>null</code> if - * there is no search result tab for the specified <code>resourceType</code> - * (or if that <code>resourceType</code> does not support filtering). - */ - protected FilterTreePane getFilterTreePaneFor(TYPE resourceType) { - return (this.currentFilterPanes.get(resourceType)); - } - - - // *** Callback for ActionListener interface *** - - public void actionPerformed(ActionEvent e) - { - // FIXME -- remove this... -// if (e.getSource().equals(bRefreshLastSearch)) -// { -// // restore state of the search options panel -// pluginPerspectiveMainComponent.getSearchTab().restoreSearchOptions(siPreviousSearch); -// -// // completely re-run the previous search -// startNewSearch(siPreviousSearch); -// } -// else if (e.getSource().equals(bClearSearchResults)) -// { -// // manual request to clear results of previous search -// -// // if any search thread was running, deactivate it as well -// if (isSearchThreadRunning()) { -// vCurrentSearchThreadID.set(0, null); -// } -// -// // changing both - spinner image and the status text simultaneously -// setSearchStatusText("No searches were made yet", false); -// -// // removed the previous search, hence makes no sense to allow to clear "previous" results again -// bClearSearchResults.setEnabled(false); -// -// // only remove data about previous search and disable refresh button -// // if no search thread is currently running - otherwise keep the button -// // enabled in case there is a need to re-start the search if it's frozen -// if (!isSearchThreadRunning()) { -// siPreviousSearch = null; -// bRefreshLastSearch.setEnabled(false); -// } -// -// // also notify tabbed results panel, so that it removes the actual search results -// searchResultsPanel.clearPreviousSearchResults(); -// } -// else if (e.getSource().equals(this.jclPreviewCurrentFilteringCriteria)) -// { -// // open a preview window showing current filtering settings -// SwingUtilities.invokeLater(new Runnable() -// { -// public void run() { -// ServiceFilteringSettingsPreview p = new ServiceFilteringSettingsPreview(siPreviousSearch.getFilteringSettings()); -// p.setVisible(true); -// } -// }); -// -// } - } - - - // *** Callbacks for SearchInstanceTracker interface *** - - public synchronized void clearPreviousSearchInstances() { - this.currentSearchInstances.clear(); - } - - public synchronized boolean isCurrentSearchInstance(TYPE searchType, SearchInstance searchInstance) { - // NB! it is crucial to perform test by reference here (hence the use of "==", not equals()!) - return (this.currentSearchInstances.get(searchType) == searchInstance); - } - - public synchronized void registerSearchInstance(TYPE searchType, SearchInstance searchInstance) { - this.currentSearchInstances.put(searchType, searchInstance); - } - - public synchronized SearchInstance getCurrentSearchInstance(TYPE searchType) { - return this.currentSearchInstances.get(searchType); - } - -public void clearListingPanels() { - for (SearchResultsListingPanel listingPanel : searchResultListings.values()) { - listingPanel.resetSearchResultsListing(true); - } - for (TYPE t : searchResultListings.keySet()) { - setDefaultTitleForTab(t); - } - -} - -public void clearSearch() { - clearPreviousSearchInstances(); - clearListingPanels(); - for (FilterTreePane treePanel : currentFilterPanes.values()) { - treePanel.reset(); - } -} - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52817a33/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsRenderer.java ---------------------------------------------------------------------- diff --git a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsRenderer.java b/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsRenderer.java deleted file mode 100644 index 7c39fc9..0000000 --- a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/SearchResultsRenderer.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.apache.taverna.biocatalogue.ui.search_results; -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.apache.taverna.biocatalogue.model.search.SearchInstance; - -/** - * This interfaces avoids coupling of search engine classes - * directly with the UI classes. - * - * Search engines would send new chunks of search results - * to the <code>SearchResultsRenderer</code> as soon as - * they become available. - * - * @author Sergejs Aleksejevs - */ -public interface SearchResultsRenderer -{ - /** - * Render initial fragment of search results. This includes - * creating a new <code>ListModel</code> in the results listing - * and populating it with the first chunk of results and placeholders - * for those results that haven't been fetched yet. - * -// * @param searchThreadID This is the ID of the thread that initiated search // FIXME -// * from within the UI component, rather than the ID of -// * the real worker search engine's search thread. -// * It is used to test whether that thread is still active - -// * to determine whether the partial results need to be rendered. - * @param si The search instance containing partial search results to be rendered. - */ - void renderInitialResults(SearchInstance si); - - - /** - * Update the results listing with a specific fragment of the collection - * of search results. - * - * @param si The search instance containing partial search results to be rendered. - * @param startIndex First index in the result collection to update. - * @param count Number of result listing entries to update. - * <br/> - * At most <code>count</code> results will be rendered - less can be rendered - * if end of result list is reached earlier. <code>count</code> is normally - * just a page size for a specific resource type. - */ - void renderFurtherResults(SearchInstance si, int startIndex, int count); - -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/52817a33/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/ServiceListCellRenderer.java ---------------------------------------------------------------------- diff --git a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/ServiceListCellRenderer.java b/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/ServiceListCellRenderer.java deleted file mode 100644 index c7cf5ba..0000000 --- a/taverna-perspective-biocatalogue/src/main/java/org/apache/taverna/biocatalogue/ui/search_results/ServiceListCellRenderer.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.apache.taverna.biocatalogue.ui.search_results; -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.ImageIcon; -import javax.swing.JLabel; - -import org.apache.commons.lang.StringEscapeUtils; -import org.biocatalogue.x2009.xml.rest.Location; -import org.biocatalogue.x2009.xml.rest.ResourceLinkWithString; -import org.biocatalogue.x2009.xml.rest.Service; -import org.biocatalogue.x2009.xml.rest.ServiceSummary.Provider; - -import org.apache.taverna.biocatalogue.model.LoadingExpandedResource; -import org.apache.taverna.biocatalogue.model.LoadingResource; -import org.apache.taverna.biocatalogue.model.Resource; -import org.apache.taverna.biocatalogue.model.Resource.TYPE; -import org.apache.taverna.biocatalogue.model.ResourceManager; -import org.apache.taverna.biocatalogue.model.Util; -import org.apache.taverna.ui.perspectives.biocatalogue.integration.health_check.ServiceMonitoringStatusInterpreter; - - -/** - * This list cell renderer is will display (web) Service items in the search results - * list box. - * - * In the collapsed state, four data items will be shown per service: status (as per monitoring data), - * service type (SOAP / REST), the name of the service and its description. - * - * In the expanded state, other details are added to the ones above: service categories, locations, - * endpoints and providers. - * - * @author Sergejs Aleksejevs - */ -@SuppressWarnings("serial") -public class ServiceListCellRenderer extends ExpandableOnDemandLoadedListCellRenderer -{ - private JLabel jlTypeIcon; - private JLabel jlItemStatus; - private JLabel jlItemTitle; - private JLabel jlDescription; - - private GridBagConstraints c; - - - public ServiceListCellRenderer() { - /* do nothing */ - } - - - /** - * This entry can be in one of two states: - * -- containing only the name of the resource and NOT loading further details; - * -- containing only the name of the resource and LOADING further details. - * - * @param itemToRender - * @return - */ - protected GridBagConstraints prepareInitiallyLoadingEntry(Object itemToRender) - { - TYPE resourceType = determineResourceType(itemToRender); - LoadingResource resource = (LoadingResource)itemToRender; - - jlTypeIcon = new JLabel(resourceType.getIcon()); - jlItemStatus = new JLabel(ResourceManager.getImageIcon(ResourceManager.SERVICE_STATUS_UNKNOWN_ICON)); - - jlItemTitle = new JLabel(Resource.getDisplayNameForResource(resource), JLabel.LEFT); - jlItemTitle.setForeground(Color.decode("#AD0000")); // very dark red - jlItemTitle.setFont(jlItemTitle.getFont().deriveFont(Font.PLAIN, jlItemTitle.getFont().getSize() + 2)); - - jlDescription = resource.isLoading() ? loaderBarAnimationGrey : loaderBarAnimationGreyStill; - - return (arrangeLayout(false)); - } - - - /** - * - * @param itemToRender - * @param expandedView <code>true</code> to indicate that this method generates the top - * fragment of the expanded list entry for this SOAP operation / REST method. - * @return - */ - protected GridBagConstraints prepareLoadedEntry(Object itemToRender, boolean selected) - { - TYPE resourceType = determineResourceType(itemToRender); - Service service = (Service)itemToRender;; - - // service type - if (service.getServiceTechnologyTypes() != null && service.getServiceTechnologyTypes().getTypeList().size() > 0) - { - if (service.getServiceTechnologyTypes().getTypeList().size() > 1 && - !(service.getServiceTechnologyTypes().getTypeList().get(0).toString().equalsIgnoreCase("SOAP")) && - service.getServiceTechnologyTypes().getTypeList().get(1).toString().equalsIgnoreCase("SOAPLAB") - ) - { - jlTypeIcon = new JLabel(ResourceManager.getImageIcon(ResourceManager.SERVICE_TYPE_MULTITYPE_ICON)); - } - else if (service.getServiceTechnologyTypes().getTypeArray(0).toString().equalsIgnoreCase("SOAP")) { - jlTypeIcon = new JLabel(ResourceManager.getImageIcon(ResourceManager.SERVICE_TYPE_SOAP_ICON)); - } - else if (service.getServiceTechnologyTypes().getTypeArray(0).toString().equalsIgnoreCase("REST")) { - jlTypeIcon = new JLabel(ResourceManager.getImageIcon(ResourceManager.SERVICE_TYPE_REST_ICON)); - } - } - else { - // can't tell the type - just show as a service of no particular type - jlTypeIcon = new JLabel(resourceType.getIcon()); - } - - - // service status - jlItemStatus = new JLabel(ServiceMonitoringStatusInterpreter.getStatusIcon(service, true)); - - jlItemTitle = new JLabel(Resource.getDisplayNameForResource(service), JLabel.LEFT); - jlItemTitle.setForeground(Color.decode("#AD0000")); // very dark red - jlItemTitle.setFont(jlItemTitle.getFont().deriveFont(Font.PLAIN, jlItemTitle.getFont().getSize() + 2)); - - int descriptionMaxLength = DESCRIPTION_MAX_LENGTH_EXPANDED; - String strDescription = Util.stripAllHTML(service.getDescription()); - strDescription = (strDescription == null || strDescription.length() == 0 ? - "<font color=\"gray\">no description</font>" : - StringEscapeUtils.escapeHtml(Util.ensureLineLengthWithinString(strDescription, LINE_LENGTH, false))); - - if (strDescription.length() > descriptionMaxLength) { - strDescription = strDescription.substring(0, descriptionMaxLength) + "<font color=\"gray\">(...)</font>"; - } - strDescription = "<html><b>Description: </b>" + strDescription + "</html>"; - jlDescription = new JLabel(strDescription); - - return (arrangeLayout(true)); - } - - - /** - * @return Final state of the {@link GridBagConstraints} instance - * that was used to lay out components in the panel. - */ - private GridBagConstraints arrangeLayout(boolean showActionButtons) - { - // POPULATE PANEL WITH PREPARED COMPONENTS - this.setLayout(new GridBagLayout()); - c = new GridBagConstraints(); - c.anchor = GridBagConstraints.NORTHWEST; - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridx = 0; - c.gridy = 0; - c.weightx = 0; - c.insets = new Insets(10, 6, 6, 3); - this.add(jlTypeIcon, c); - - c.gridx++; - c.insets = new Insets(10, 3, 6, 3); - this.add(jlItemStatus, c); - - c.gridx++; - c.weightx = 1.0; - c.insets = new Insets(10, 3, 6, 3); - this.add(jlItemTitle, c); - - if (showActionButtons) { - c.gridx++; - c.gridheight = 3; - c.weightx = 0; - c.weighty = 1.0; - jlExpand = new JLabel(ResourceManager.getImageIcon(ResourceManager.FOLD_ICON)); - this.add(jlExpand, c); - } - - c.gridx = 2; - c.gridy++; - c.gridheight = 1; - c.weightx = 1.0; - c.weighty = 0; - c.insets = new Insets(3, 3, 3, 3); - this.add(jlDescription, c); - - return (c); - } - - - - protected void prepareLoadingExpandedEntry(Object itemToRender) - { - LoadingExpandedResource expandedResource = (LoadingExpandedResource) itemToRender; - GridBagConstraints c = prepareLoadedEntry(expandedResource.getAssociatedObj(), false); - - if (expandedResource.isLoading()) - { - c.gridx = 0; - c.gridy++; - c.gridwidth = 3; - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1.0; - this.add(loaderBarAnimationOrange, c); - } - else - { - // *** additional data for this Web Service operations *** - Service service = (Service) expandedResource.getAssociatedObj(); - - - // -- categories -- - int categoryCount = service.getSummary().getCategoryList().size(); - String categoryString = ""; - if (categoryCount > 0) { - List<String> categoryNames = new ArrayList<String>(); - for (ResourceLinkWithString category : service.getSummary().getCategoryList()) { - categoryNames.add(category.getStringValue()); - } - categoryString = "<html><b>" + Util.pluraliseNoun("Category", categoryCount) + ": </b>" + StringEscapeUtils.escapeHtml(Util.join(categoryNames, ", ")) + "</html>"; - } - else { - categoryString = "<html><b>Category: </b><font color=\"gray\">unknown</font></html>"; - } - - c.gridy++; - this.add(new JLabel(categoryString),c); - - - // -- endpoints -- - int endpointCount = service.getSummary().getEndpointList().size(); - String endpointString = ""; - if (endpointCount > 0) { - endpointString = "<html><b>" + Util.pluraliseNoun("Endpoint", endpointCount) + ": </b>" + - StringEscapeUtils.escapeHtml(Util.join(service.getSummary().getEndpointList(), ", ")) + "</html>"; - } - else { - endpointString = "<html><b>Endpoint: </b><font color=\"gray\">unknown</font></html>"; - } - - c.gridy++; - this.add(new JLabel(endpointString), c); - - - // -- providers -- - int providerCount = service.getSummary().getProviderList().size(); - String providerString = ""; - if (providerCount > 0) { - List<String> providerNames = new ArrayList<String>(); - for (Provider serviceProvider : service.getSummary().getProviderList()) { - providerNames.add(serviceProvider.getName()); - } - providerString = "<html><b>" + Util.pluraliseNoun("Provider", providerCount) + ": </b>" + StringEscapeUtils.escapeHtml(Util.join(providerNames, ", ")) + "</html>"; - } - else { - providerString = "<html><b>Provider: </b><font color=\"gray\">unknown</font></html>"; - } - - c.gridy++; - this.add(new JLabel(providerString),c); - - - // -- locations -- - int locationCount = service.getSummary().getLocationList().size(); - String locationString = ""; - List<String> locations = new ArrayList<String>(); - if (locationCount > 0) { - for (Location location : service.getSummary().getLocationList()) { - List<String> locationNameFragments = new ArrayList<String>(); - locationNameFragments.add(location.getCity()); - locationNameFragments.add(location.getCountry()); - locations.add(Util.join(locationNameFragments, ", ")); - } - } - locationString = "<html><b>" + Util.pluraliseNoun("Location", locations.size()) + ": </b>" + - (locations.size() > 0 ? StringEscapeUtils.escapeHtml(Util.join(locations, "; ")) : "<font color=\"gray\">unknown</font>") + - "</html>"; - - c.gridy++; - c.insets = new Insets(3, 3, 12, 3); - this.add(new JLabel(locationString),c); - } - } - - -@Override -boolean shouldBeHidden(Object itemToRender) { - return false; -} - -}