diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelper.java index 450de721aca12e4de8007f218cb351db00931c03..dbc3bc189420f7091530fe33bca79b976d67fdde 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelper.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelper.java @@ -16,10 +16,12 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.extjs.gxt.ui.client.widget.MessageBox; +import com.google.gwt.user.client.rpc.AsyncCallback; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DefaultTabItem; @@ -35,15 +37,22 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample. import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes; import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.PermlinkUtilities; import ch.systemsx.cisd.openbis.generic.shared.basic.SearchlinkUtilities; import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BatchOperationKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleAttributeSearchFieldKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection; /** * A class with helper methods for URL parameters handling and opening initial tab. @@ -195,12 +204,17 @@ public final class UrlParamsHelper private void openInitialEntitySearch(String entityKindValue) throws UserFailureException { EntityKind entityKind = getEntityKind(entityKindValue); + if (EntityKind.SAMPLE != entityKind) + { + throw new UserFailureException( + "URLs for searching openBIS only support SAMPLE searches. Entity " + + entityKind + " is not supported."); + } - String searchStringOrNull = - tryGetUrlParamValue(SearchlinkUtilities.SEARCH_FIELD_PARAMETER_KEY); - if (searchStringOrNull != null) + String codeStringOrNull = tryGetUrlParamValue(SearchlinkUtilities.CODE_PARAMETER_KEY); + if (codeStringOrNull != null) { - openEntitySearch(entityKind, searchStringOrNull); + openEntitySearch(entityKind, codeStringOrNull); } else { // default the search string @@ -224,9 +238,36 @@ public final class UrlParamsHelper } - private void openEntitySearch(EntityKind entityKind, String searchString) + private void openEntitySearch(EntityKind entityKind, String codeString) + { + ListSampleDisplayCriteria displayCriteria = + getListSampleDisplayCriteriaForCodeString(codeString); + + viewContext.getCommonService().listSamples(displayCriteria, + new OpenEntitySearchTabCallback(codeString, displayCriteria)); + } + + /** + * Convert the code into a ListSampleDisplayCriteria -- a LSDC is used to pass the search + * parameters to the server. + */ + private ListSampleDisplayCriteria getListSampleDisplayCriteriaForCodeString( + String codeString) { - DispatcherHelper.dispatchNaviEvent(new OpenEntitySearchTabCallback(searchString)); + // Create a display criteria object for the search string + ListSampleDisplayCriteria displayCriteria = ListSampleDisplayCriteria.createForSearch(); + DetailedSearchCriterion searchCriterion = + new DetailedSearchCriterion(DetailedSearchField + .createAttributeField(SampleAttributeSearchFieldKind.CODE), codeString); + + DetailedSearchCriteria searchCriteria = new DetailedSearchCriteria(); + searchCriteria.setConnection(SearchCriteriaConnection.MATCH_ALL); + ArrayList<DetailedSearchCriterion> criterionList = + new ArrayList<DetailedSearchCriterion>(); + criterionList.add(searchCriterion); + searchCriteria.setCriteria(criterionList); + displayCriteria.updateSearchCriteria(searchCriteria); + return displayCriteria; } private EntityKind getEntityKind(String entityKindValueOrNull) @@ -266,13 +307,63 @@ public final class UrlParamsHelper } } - private class OpenEntitySearchTabCallback implements ITabItemFactory + private class OpenEntitySearchTabCallback implements + AsyncCallback<ResultSetWithEntityTypes<Sample>> + { + private final String codeString; + + private final ListSampleDisplayCriteria displayCriteria; + + private OpenEntitySearchTabCallback(String codeString, + ListSampleDisplayCriteria displayCriteria) + { + this.codeString = codeString; + this.displayCriteria = displayCriteria; + } + + public final void onFailure(Throwable caught) + { + // Error in the search -- notify the user + MessageBox.alert("Error", caught.getMessage(), null); + } + + public final void onSuccess(ResultSetWithEntityTypes<Sample> result) + { + switch (result.getResultSet().getTotalLength()) + { + // Nothing found -- notify the user + case 0: + MessageBox.alert("Error", + "No samples with code " + codeString + " were found.", null); + break; + // One result found -- show it in the details view + case 1: + Sample sample = result.getResultSet().getList().get(0).getOriginalObject(); + OpenEntityDetailsTabAction detailsAction = + new OpenEntityDetailsTabAction(sample, viewContext); + detailsAction.execute(); + break; + + // Multiple results found -- show them in a grid + default: + OpenEntitySearchGridTabAction searchAction = + new OpenEntitySearchGridTabAction(codeString, displayCriteria); + + DispatcherHelper.dispatchNaviEvent(searchAction); + + break; + } + } + } + + private class OpenEntitySearchGridTabAction implements ITabItemFactory { - private final String searchString; + private final ListSampleDisplayCriteria displayCriteria; - OpenEntitySearchTabCallback(String searchString) + private OpenEntitySearchGridTabAction(String codeString, + ListSampleDisplayCriteria displayCriteria) { - this.searchString = searchString; + this.displayCriteria = displayCriteria; } private String getMessage(String key) @@ -290,9 +381,8 @@ public final class UrlParamsHelper public ITabItem create() { IDisposableComponent browser = - SampleSearchHitGrid.createWithInitialSearchCriterion( - (IViewContext<ICommonClientServiceAsync>) viewContext, - SampleAttributeSearchFieldKind.CODE, searchString); + SampleSearchHitGrid.createWithInitialDisplayCriteria( + (IViewContext<ICommonClientServiceAsync>) viewContext, displayCriteria); return createTab(Dict.SAMPLE_SEARCH, browser); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleSearchHitGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleSearchHitGrid.java index 98bbee11ddfcf90e07d8679a73b43108ab99aae1..dbce90e9d33597362745548b7be70e5376926a18 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleSearchHitGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleSearchHitGrid.java @@ -34,9 +34,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search. import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.search.IDetailedSearchHitGrid; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; /** @@ -70,20 +70,32 @@ public class SampleSearchHitGrid extends SampleBrowserGrid implements IDetailedS return grid.asDisposableWithToolbar(toolbar); } - public static IDisposableComponent createWithInitialSearchCriterion( + /** + * Create a search hit grid and initialize the search with the display criteria. N.b. The + * implementation of this method assumes that the display criteria has one and only one + * criterion. + */ + public static IDisposableComponent createWithInitialDisplayCriteria( final IViewContext<ICommonClientServiceAsync> viewContext, - IAttributeSearchFieldKind initialKind, String initialSearchString) + ListSampleDisplayCriteria displayCriteria) { + assert displayCriteria.getSearchCriteria().getCriteria().size() == 1; + + // User the caller-provided display criteria ISampleCriteriaProvider criteriaProvider = - new SampleCriteriaProvider(viewContext, ListSampleDisplayCriteria.createForSearch()); + new SampleCriteriaProvider(viewContext, displayCriteria); SampleSearchHitGrid grid = new SampleSearchHitGrid(viewContext, criteriaProvider); final DetailedSearchWindow searchWindow = new DetailedSearchWindow(viewContext, EntityKind.SAMPLE); + // Extract the search criterion (it is assumed that there is only one -- see method comment) + DetailedSearchCriterion searchCriterion = + displayCriteria.getSearchCriteria().getCriteria().get(0); + // Set the initial search string before creating the toolbar because the toolbar will use // the initial search string in its own initialization. - searchWindow.setInitialSearchCriterion(initialKind, initialSearchString); - criteriaProvider.tryGetCriteria().updateSearchCriteria(searchWindow.tryGetCriteria()); + searchWindow.setInitialSearchCriterion(searchCriterion.getField(), searchCriterion + .getValue()); final DetailedSearchToolbar toolbar = new DetailedSearchToolbar(grid, viewContext.getMessage(Dict.BUTTON_CHANGE_QUERY), diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java index c5307a3b26c7bef28ec75cb5a0ee5e49ae57de26..9d4f8f4bc0bc0eebcf390e4be161b9e5fcb2c815 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriteriaWidget.java @@ -26,8 +26,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; /** @@ -177,11 +177,11 @@ public class DetailedSearchCriteriaWidget extends VerticalPanel * Set the initial search string to the argument. This should be called after creation but * before the user has had a chance to use the window, otherwise user input may be overwritten. */ - public void setInitialSearchCriterion(IAttributeSearchFieldKind initialKind, + public void setInitialSearchCriterion(DetailedSearchField initialField, String initialSearchString) { DetailedSearchCriterionWidget widget = criteriaWidgets.get(0); - widget.setSearchCriterion(initialKind, initialSearchString); + widget.setSearchCriterion(initialField, initialSearchString); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java index 032c5a60f4a2dc3aa871a3b770704888333d5823..a474aa0afc31f7e92eaa752720f083b3794ccae0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchCriterionWidget.java @@ -35,7 +35,6 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.Strin import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriterion; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; /** @@ -203,11 +202,25 @@ public class DetailedSearchCriterionWidget extends HorizontalPanel /** * Set the search string to the argument. */ - public void setSearchCriterion(IAttributeSearchFieldKind kind, String searchString) + public void setSearchCriterion(DetailedSearchField field, String searchString) { - DetailedSearchFieldComboModel model = - new DetailedSearchFieldComboModel(kind.getDescription(), DetailedSearchField - .createAttributeField(kind)); + String description = ""; + switch (field.getKind()) + { + case ATTRIBUTE: + description = field.getAttributeCode(); + break; + case PROPERTY: + description = field.getPropertyCode(); + break; + case ANY_FIELD: + description = "Any Field"; + break; + case ANY_PROPERTY: + description = "Any Property"; + break; + } + DetailedSearchFieldComboModel model = new DetailedSearchFieldComboModel(description, field); nameField.setValue(model); valueField.setValue(searchString); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java index b2fc2799a2d91db9aa3e5cbf244ecea75fcbd340..9cdfac0b7b24a918527d043ea1e9c6af0e45ac0f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchToolbar.java @@ -54,7 +54,6 @@ public class DetailedSearchToolbar extends ToolBar })); if (initializeDescriptionFromSearchWindow) { - System.out.println("Desc " + searchWindow.getCriteriaDescription()); updateDescription(searchWindow.getCriteriaDescription()); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java index 6bca12ae5b291dc859e7e8705f6bfb923b38b6fb..34dca74cd94e7cdebf1a5e0c272e9367f6102f4c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/search/DetailedSearchWindow.java @@ -17,8 +17,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.help.HelpP import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractDialogWithOnlineHelp; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetSearchHitGrid; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; /** @@ -132,9 +132,9 @@ public class DetailedSearchWindow extends AbstractDialogWithOnlineHelp * does not notify the listener of any changes -- the caller must keep the window and toolbar in * sync. */ - public void setInitialSearchCriterion(IAttributeSearchFieldKind initialKind, String searchString) + public void setInitialSearchCriterion(DetailedSearchField initialField, String searchString) { // Set the widget - criteriaWidget.setInitialSearchCriterion(initialKind, searchString); + criteriaWidget.setInitialSearchCriterion(initialField, searchString); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/SearchlinkUtilities.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/SearchlinkUtilities.java index d4c11e4db0de6ef0882585b5fdaeea7da8abe0b7..ae9a7baa186b514843038b28c273cd9b659b0b89 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/SearchlinkUtilities.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/SearchlinkUtilities.java @@ -26,7 +26,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; public class SearchlinkUtilities { /** The HTTP URL parameter used to specify the entity identifier. */ - public static final String SEARCH_FIELD_PARAMETER_KEY = "searchString"; + public static final String CODE_PARAMETER_KEY = "code"; /** The HTTP URL parameter used to specify the entity kind. */ public static final String ENTITY_KIND_PARAMETER_KEY = "searchEntity"; @@ -36,7 +36,7 @@ public class SearchlinkUtilities { URLMethodWithParameters ulrWithParameters = new URLMethodWithParameters(baseIndexURL); ulrWithParameters.addParameter(ENTITY_KIND_PARAMETER_KEY, entityKind.name()); - ulrWithParameters.addParameter(SEARCH_FIELD_PARAMETER_KEY, searchString); + ulrWithParameters.addParameter(CODE_PARAMETER_KEY, searchString); return ulrWithParameters.toString(); } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelperTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelperTest.java index a1f72ed45781a937d6a0aff4ce521de996cab5d7..7699136e4a6beb4c55f4feba3d5257a4ea309b11 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelperTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/UrlParamsHelperTest.java @@ -26,6 +26,7 @@ import org.testng.annotations.Test; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.UrlParamsHelper.OpenInitialTabAction; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; @@ -161,6 +162,7 @@ public class UrlParamsHelperTest extends AssertJUnit context.assertIsSatisfied(); } + @SuppressWarnings("unchecked") @Test public void testOpenInitialSearchTab() { @@ -169,17 +171,16 @@ public class UrlParamsHelperTest extends AssertJUnit { allowing(viewContext).getCommonService(); will(returnValue(commonService)); - // - // one(commonService).getEntityInformationHolder(with(EntityKind.SAMPLE), - // with("20100104150239401-871"), - // with(Expectations.any(AbstractAsyncCallback.class))); + + one(commonService).listSamples( + with(Expectations.any(ListSampleDisplayCriteria.class)), + with(Expectations.any(AbstractAsyncCallback.class))); } }); final UrlParamsHelper urlParamsHelper = new UrlParamsHelper(viewContext); - urlParamsHelper - .initializeUrlParameters("searchEntity=SAMPLE&searchString=20100104150239401-871"); + urlParamsHelper.initializeUrlParameters("searchEntity=SAMPLE&code=CL1"); IDelegatedAction action = urlParamsHelper.getOpenInitialTabAction(); action.execute(); @@ -187,8 +188,9 @@ public class UrlParamsHelperTest extends AssertJUnit context.assertIsSatisfied(); } + @SuppressWarnings("unchecked") @Test - public void testOpenInitialSearchTabDefaultingSearchString() + public void testOpenInitialSearchTabWithoutCode() { context.checking(new Expectations() { @@ -196,20 +198,49 @@ public class UrlParamsHelperTest extends AssertJUnit allowing(viewContext).getCommonService(); will(returnValue(commonService)); - // one(commonService).getEntityInformationHolder(with(EntityKind.SAMPLE), - // with("20100104150239401-871"), - // with(Expectations.any(AbstractAsyncCallback.class))); + one(commonService).listSamples( + with(Expectations.any(ListSampleDisplayCriteria.class)), + with(Expectations.any(AbstractAsyncCallback.class))); } }); final UrlParamsHelper urlParamsHelper = new UrlParamsHelper(viewContext); - urlParamsHelper - .initializeUrlParameters("searchEntity=SAMPLE&searchString=20100104150239401-871"); + urlParamsHelper.initializeUrlParameters("searchEntity=SAMPLE"); IDelegatedAction action = urlParamsHelper.getOpenInitialTabAction(); action.execute(); context.assertIsSatisfied(); } + + @Test + public void testOpenInitialSearchTabWithDataset() + { + context.checking(new Expectations() + { + { + allowing(viewContext).getCommonService(); + will(returnValue(commonService)); + } + + }); + + final UrlParamsHelper urlParamsHelper = new UrlParamsHelper(viewContext); + urlParamsHelper.initializeUrlParameters("searchEntity=DATA_SET"); + + OpenInitialTabAction action = + (OpenInitialTabAction) urlParamsHelper.getOpenInitialTabAction(); + + try + { + action.openInitialTabUnderExceptionHandler(); + fail("Only SAMPLE is supported by the search link mechanism right now."); + } catch (UserFailureException expected) + { + // Do nothing -- this should happen + } + + context.assertIsSatisfied(); + } }