From 841373a22a6b6df372285bed75965c28db7ff7b0 Mon Sep 17 00:00:00 2001 From: tpylak <tpylak> Date: Mon, 30 Mar 2009 13:34:47 +0000 Subject: [PATCH] LMS-751 Automatic refresh of _grid_ tabs when items are changed in other tabs SVN: 10471 --- .../application/AbstractAsyncCallback.java | 26 +- .../application/MatchingEntitiesPanel.java | 31 +- .../web/client/application/SearchWidget.java | 11 +- .../framework/ComponentProvider.java | 812 ++++++++++-------- .../framework/ContentPanelAdapter.java | 24 +- .../application/framework/DefaultTabItem.java | 61 +- .../IDatabaseModificationObserver.java | 42 + .../application/framework/ITabItem.java | 13 +- .../LastModificationStateUpdater.java | 114 +++ .../application/framework/MainTabPanel.java | 49 +- .../ui/AbstractEntityTypeGrid.java | 8 + .../ui/data/DataSetSearchHitGrid.java | 14 + .../ui/experiment/ExperimentBrowserGrid.java | 15 + .../ui/grid/AbstractBrowserGrid.java | 36 +- .../ui/grid/DisposableComponent.java | 5 +- .../ui/material/MaterialBrowserGrid.java | 12 + .../application/ui/project/ProjectGrid.java | 8 + .../PropertyTypeAssignmentGrid.java | 8 + .../ui/property_type/PropertyTypeGrid.java | 11 + .../ui/sample/SampleBrowserGrid.java | 12 + .../ui/vocabulary/VocabularyGrid.java | 10 +- .../ui/vocabulary/VocabularyTermGrid.java | 23 +- .../DatabaseLastModificationAdvisor.java | 4 +- .../openbis/generic/shared/ICommonServer.java | 1 + .../basic/dto/DatabaseModificationKind.java | 24 +- .../basic/dto/LastModificationState.java | 23 +- .../experiment/ExperimentDataSetBrowser.java | 25 +- .../sample/SampleDataSetBrowser.java | 15 +- .../shared/ICommonServer.java.expected | 6 +- 29 files changed, 968 insertions(+), 475 deletions(-) create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java index a239c11c32b..8e98dcafaf7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java @@ -86,21 +86,31 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> // can be null only during tests protected final IViewContext<?> viewContext; - /** - * Creates an instance for the specified view context. - */ + // should the login page appear when the 'session terminated' exception occurs + private final boolean reloadWhenSessionTerminated; + public AbstractAsyncCallback(final IViewContext<?> viewContext) { - this(viewContext, null); + this(viewContext, false); } - /** - * Creates an instance for the specified view context. - */ public AbstractAsyncCallback(final IViewContext<?> viewContext, final ICallbackListener<T> callbackListenerOrNull) + { + this(viewContext, callbackListenerOrNull, true); + } + + public AbstractAsyncCallback(final IViewContext<?> viewContext, + boolean reloadWhenSessionTerminated) + { + this(viewContext, null, reloadWhenSessionTerminated); + } + + private AbstractAsyncCallback(final IViewContext<?> viewContext, + final ICallbackListener<T> callbackListenerOrNull, boolean reloadWhenSessionTerminated) { this.viewContext = viewContext; + this.reloadWhenSessionTerminated = reloadWhenSessionTerminated; // If static ICallbackListener is not DEFAULT_CALLBACK_LISTENER, then we assume being in // testing mode. So no customized ICallbackListener (specified in the constructor) possible. if (staticCallbackListener != DEFAULT_CALLBACK_LISTENER) @@ -206,7 +216,7 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> @Override public void windowHide(WindowEvent we) { - if (viewContext != null) + if (viewContext != null && reloadWhenSessionTerminated) { final IPageController pageController = viewContext.getPageController(); pageController.reload(true); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java index de5f50f5899..3dcb9ace1c1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java @@ -16,6 +16,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import java.util.List; import com.extjs.gxt.ui.client.XDOM; @@ -32,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.ICl import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.IEditableEntity; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractBrowserGrid; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableComponent; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.MatchingEntity; @@ -39,10 +43,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SearchableEntity; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * A {@link LayoutContainer} extension which displays the matching entities. @@ -59,17 +65,27 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma private final String queryText; - MatchingEntitiesPanel(final IViewContext<ICommonClientServiceAsync> viewContext, - final SearchableEntity searchableEntity, final String queryText) + public DisposableComponent asDisposableComponent() + { + return asDisposableWithoutToolbar(); + } + + public MatchingEntitiesPanel(IViewContext<ICommonClientServiceAsync> viewContext, + SearchableEntity searchableEntity, String queryText) { // NOTE: refreshAutomatically is false, refreshing should be called manually super(viewContext, GRID_ID, false, false); this.searchableEntity = searchableEntity; this.queryText = queryText; - setId(PREFIX + XDOM.getUniqueId()); + setId(createId()); updateDefaultRefreshButton(); } + private static String createId() + { + return PREFIX + XDOM.getUniqueId(); + } + @Override protected boolean isRefreshEnabled() { @@ -139,4 +155,13 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma MatchingEntityColumnKind.MATCHING_FIELD }); } + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.MATERIAL), edit(ObjectKind.MATERIAL), + createOrDelete(ObjectKind.SAMPLE), edit(ObjectKind.SAMPLE), + createOrDelete(ObjectKind.EXPERIMENT), edit(ObjectKind.EXPERIMENT), + createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT), + createOrDelete(ObjectKind.VOCABULARY_TERM) }; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java index 4ca2aa0770f..34e553889ac 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchWidget.java @@ -148,10 +148,12 @@ public final class SearchWidget extends LayoutContainer enableSearch(false); final SearchableEntity selectedSearchableEntityOrNull = entityChooser.getSelectedSearchableEntity(); + final MatchingEntitiesPanel matchingEntitiesGrid = new MatchingEntitiesPanel(viewContext, selectedSearchableEntityOrNull, queryText); String title = createTabTitle(queryText); - final ITabItemFactory tabFactory = createTabFactory(matchingEntitiesGrid, title); + final ITabItemFactory tabFactory = + createTabFactory(matchingEntitiesGrid, title, viewContext); matchingEntitiesGrid.refresh(new IDataRefreshCallback() { @@ -184,9 +186,12 @@ public final class SearchWidget extends LayoutContainer } private static ITabItemFactory createTabFactory( - final MatchingEntitiesPanel matchingEntitiesPanel, String title) + final MatchingEntitiesPanel matchingEntitiesPanel, String title, + IViewContext<?> viewContext) { - final DefaultTabItem tab = new DefaultTabItem(title, matchingEntitiesPanel, false); + final ITabItem tab = + DefaultTabItem.create(title, matchingEntitiesPanel.asDisposableComponent(), + viewContext); // this tab cannot be opened for the second time, so we can create it outside of the // factory return new ITabItemFactory() diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java index 9bbe1715446..7bb8aa3e130 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java @@ -16,6 +16,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; +import com.extjs.gxt.ui.client.widget.Component; + import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict; import ch.systemsx.cisd.openbis.generic.client.web.client.application.GroupsView; @@ -43,8 +45,6 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabul import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.vocabulary.VocabularyRegistrationForm; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; -import com.extjs.gxt.ui.client.widget.Component; - /** * Creates and provides GUI modules/components (such as sample browser). * <p> @@ -53,373 +53,443 @@ import com.extjs.gxt.ui.client.widget.Component; * * @author Izabela Adamczyk */ -public final class ComponentProvider { - private final CommonViewContext viewContext; - - ComponentProvider(final CommonViewContext viewContext) { - this.viewContext = viewContext; - } - - private String getMessage(String key) { - return viewContext.getMessage(key); - } - - public final ITabItemFactory getSampleBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent browser = SampleBrowserGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.SAMPLE_BROWSER), - browser); - } - - public String getId() { - return SampleBrowserGrid.BROWSER_ID; - } - }; - } - - public final ITabItemFactory getMaterialBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent browser = MaterialBrowserGrid - .createWithTypeChooser(viewContext); - return DefaultTabItem.create(getMessage(Dict.MATERIAL_BROWSER), - browser); - } - - public String getId() { - return MaterialBrowserGrid.BROWSER_ID; - } - }; - } - - public final ITabItemFactory getDummyComponent() { - return new ITabItemFactory() { - public ITabItem create() { - return new DefaultTabItem(getMessage(Dict.NOT_IMPLEMENTED), - new DummyComponent(), false); - } - - public String getId() { - return DummyComponent.ID; - } - }; - } - - public final ITabItemFactory getGroupsView() { - return new ITabItemFactory() { - public ITabItem create() { - return new ContentPanelAdapter(new GroupsView(viewContext), - false); - } - - public String getId() { - return GroupsView.ID; - } - }; - } - - public final ITabItemFactory getRolesView() { - return new ITabItemFactory() { - public ITabItem create() { - return new ContentPanelAdapter(new RolesView(viewContext), - false); - } - - public String getId() { - return RolesView.ID; - } - }; - } - - public final ITabItemFactory getPersonsView() { - return new ITabItemFactory() { - public ITabItem create() { - return new ContentPanelAdapter(new PersonsView(viewContext), - false); - } - - public String getId() { - return PersonsView.ID; - } - }; - } - - public final ITabItemFactory getSampleRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new SampleRegistrationPanel(viewContext); - return new DefaultTabItem(getMessage(Dict.SAMPLE_REGISTRATION), - component, true); - } - - public String getId() { - return SampleRegistrationPanel.ID; - } - }; - } - - public final ITabItemFactory getExperimentRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new ExperimentRegistrationPanel( - viewContext); - return new DefaultTabItem( - getMessage(Dict.EXPERIMENT_REGISTRATION), component, - true); - } - - public String getId() { - return ExperimentRegistrationPanel.ID; - } - }; - } - - public final ITabItemFactory getSampleBatchRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new SampleBatchRegistrationPanel( - viewContext); - return new DefaultTabItem( - getMessage(Dict.SAMPLE_BATCH_REGISTRATION), component, - true); - } - - public String getId() { - return SampleBatchRegistrationPanel.ID; - } - }; - } - - public final ITabItemFactory getMaterialBatchRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new MaterialBatchRegistrationPanel( - viewContext); - return new DefaultTabItem(getMessage(Dict.MATERIAL_IMPORT), - component, true); - } - - public String getId() { - return MaterialBatchRegistrationPanel.ID; - } - }; - } - - public final ITabItemFactory getVocabularyRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new VocabularyRegistrationForm( - viewContext); - return new DefaultTabItem( - getMessage(Dict.VOCABULARY_REGISTRATION), component, - true); - } - - public String getId() { - return VocabularyRegistrationForm.ID; - } - }; - } - - public final ITabItemFactory getProjectRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new ProjectRegistrationForm(viewContext); - return new DefaultTabItem( - getMessage(Dict.PROJECT_REGISTRATION), component, true); - } - - public String getId() { - return ProjectRegistrationForm.ID; - } - }; - } - - public final ITabItemFactory getVocabularyBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = VocabularyGrid - .create(viewContext); - return DefaultTabItem.create( - getMessage(Dict.VOCABULARY_BROWSER), component); - } - - public String getId() { - return VocabularyGrid.GRID_ID; - } - }; - } - - public final ITabItemFactory getProjectBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = ProjectGrid.create(viewContext); - return DefaultTabItem.create(getMessage(Dict.PROJECT_BROWSER), - component); - } - - public String getId() { - return ProjectGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getExperimentBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent browser = ExperimentBrowserGrid - .create(viewContext); - return DefaultTabItem.create( - getMessage(Dict.EXPERIMENT_BROWSER), browser); - } - - public String getId() { - return ExperimentBrowserGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getPropertyTypeBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = PropertyTypeGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.PROPERTY_TYPES), - component); - } - - public String getId() { - return PropertyTypeGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getPropertyTypeRegistration() { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new PropertyTypeRegistrationForm( - viewContext); - return new DefaultTabItem( - getMessage(Dict.PROPERTY_TYPE_REGISTRATION), component, - true); - } - - public String getId() { - return PropertyTypeRegistrationForm.ID; - } - }; - } - - public ITabItemFactory getPropertyTypeAssignmentBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = PropertyTypeAssignmentGrid - .create(viewContext); - return DefaultTabItem.create( - getMessage(Dict.PROPERTY_TYPE_ASSIGNMENTS), component); - } - - public String getId() { - return PropertyTypeAssignmentGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getPropertyTypeExperimentTypeAssignmentForm() { - return getPropertyTypeAssignmentForm(EntityKind.EXPERIMENT, - Dict.ASSIGN_EXPERIMENT_PROPERTY_TYPE); - } - - public ITabItemFactory getPropertyTypeMaterialTypeAssignmentForm() { - return getPropertyTypeAssignmentForm(EntityKind.MATERIAL, - Dict.ASSIGN_MATERIAL_PROPERTY_TYPE); - } - - public ITabItemFactory getPropertyTypeDataSetTypeAssignmentForm() { - return getPropertyTypeAssignmentForm(EntityKind.DATA_SET, - Dict.ASSIGN_DATA_SET_PROPERTY_TYPE); - } - - public ITabItemFactory getPropertyTypeSampleTypeAssignmentForm() { - return getPropertyTypeAssignmentForm(EntityKind.SAMPLE, - Dict.ASSIGN_SAMPLE_PROPERTY_TYPE); - } - - private ITabItemFactory getPropertyTypeAssignmentForm( - final EntityKind entityKind, final String messageKey) { - return new ITabItemFactory() { - public ITabItem create() { - Component component = new PropertyTypeAssignmentForm( - viewContext, entityKind); - return new DefaultTabItem(getMessage(messageKey), component, - true); - } - - public String getId() { - return PropertyTypeAssignmentForm.createId(entityKind); - } - }; - } - - public ITabItemFactory getDataSetSearch() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent browser = DataSetSearchHitGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.DATA_SET_SEARCH), - browser); - } - - public String getId() { - return DataSetSearchHitGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getSampleTypeBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = SampleTypeGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.SAMPLE_TYPES), - component); - } - - public String getId() { - return SampleTypeGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getMaterialTypeBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = MaterialTypeGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.MATERIAL_TYPES), - component); - } - - public String getId() { - return MaterialTypeGrid.BROWSER_ID; - } - }; - } - - public ITabItemFactory getExperimentTypeBrowser() { - return new ITabItemFactory() { - public ITabItem create() { - DisposableComponent component = ExperimentTypeGrid - .create(viewContext); - return DefaultTabItem.create(getMessage(Dict.EXPERIMENT_TYPES), - component); - } - - public String getId() { - return ExperimentTypeGrid.BROWSER_ID; - } - }; - } +public final class ComponentProvider +{ + private final CommonViewContext viewContext; + + ComponentProvider(final CommonViewContext viewContext) + { + this.viewContext = viewContext; + } + + private String getMessage(String key) + { + return viewContext.getMessage(key); + } + + private ITabItem createTab(String dictionaryMsgKey, DisposableComponent component) + { + String title = getMessage(dictionaryMsgKey); + return DefaultTabItem.create(title, component, viewContext); + } + + // TODO 2009-03-26, Tomasz Pylak: add db modification observer support + private ITabItem createTab(String dictionaryMsgKey, Component component, + boolean isCloseConfirmationNeeded) + { + return new DefaultTabItem(getMessage(dictionaryMsgKey), component, + isCloseConfirmationNeeded); + } + + public final ITabItemFactory getSampleBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent browser = SampleBrowserGrid.create(viewContext); + return createTab(Dict.SAMPLE_BROWSER, browser); + } + + public String getId() + { + return SampleBrowserGrid.BROWSER_ID; + } + }; + } + + public final ITabItemFactory getMaterialBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent browser = + MaterialBrowserGrid.createWithTypeChooser(viewContext); + return createTab(Dict.MATERIAL_BROWSER, browser); + } + + public String getId() + { + return MaterialBrowserGrid.BROWSER_ID; + } + }; + } + + public final ITabItemFactory getDummyComponent() + { + return new ITabItemFactory() + { + public ITabItem create() + { + return createTab(Dict.NOT_IMPLEMENTED, new DummyComponent(), false); + } + + public String getId() + { + return DummyComponent.ID; + } + }; + } + + public final ITabItemFactory getGroupsView() + { + return new ITabItemFactory() + { + public ITabItem create() + { + return new ContentPanelAdapter(new GroupsView(viewContext), false); + } + + public String getId() + { + return GroupsView.ID; + } + }; + } + + public final ITabItemFactory getRolesView() + { + return new ITabItemFactory() + { + public ITabItem create() + { + return new ContentPanelAdapter(new RolesView(viewContext), false); + } + + public String getId() + { + return RolesView.ID; + } + }; + } + + public final ITabItemFactory getPersonsView() + { + return new ITabItemFactory() + { + public ITabItem create() + { + return new ContentPanelAdapter(new PersonsView(viewContext), false); + } + + public String getId() + { + return PersonsView.ID; + } + }; + } + + public final ITabItemFactory getSampleRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new SampleRegistrationPanel(viewContext); + return createTab(Dict.SAMPLE_REGISTRATION, component, true); + } + + public String getId() + { + return SampleRegistrationPanel.ID; + } + }; + } + + public final ITabItemFactory getExperimentRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new ExperimentRegistrationPanel(viewContext); + return createTab(Dict.EXPERIMENT_REGISTRATION, component, true); + } + + public String getId() + { + return ExperimentRegistrationPanel.ID; + } + }; + } + + public final ITabItemFactory getSampleBatchRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new SampleBatchRegistrationPanel(viewContext); + return createTab(Dict.SAMPLE_BATCH_REGISTRATION, component, true); + } + + public String getId() + { + return SampleBatchRegistrationPanel.ID; + } + }; + } + + public final ITabItemFactory getMaterialBatchRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new MaterialBatchRegistrationPanel(viewContext); + return createTab(Dict.MATERIAL_IMPORT, component, true); + } + + public String getId() + { + return MaterialBatchRegistrationPanel.ID; + } + }; + } + + public final ITabItemFactory getVocabularyRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new VocabularyRegistrationForm(viewContext); + return createTab(Dict.VOCABULARY_REGISTRATION, component, true); + } + + public String getId() + { + return VocabularyRegistrationForm.ID; + } + }; + } + + public final ITabItemFactory getProjectRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new ProjectRegistrationForm(viewContext); + return createTab(Dict.PROJECT_REGISTRATION, component, true); + } + + public String getId() + { + return ProjectRegistrationForm.ID; + } + }; + } + + public final ITabItemFactory getVocabularyBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = VocabularyGrid.create(viewContext); + return createTab(Dict.VOCABULARY_BROWSER, component); + } + + public String getId() + { + return VocabularyGrid.GRID_ID; + } + }; + } + + public final ITabItemFactory getProjectBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = ProjectGrid.create(viewContext); + return createTab(Dict.PROJECT_BROWSER, component); + } + + public String getId() + { + return ProjectGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getExperimentBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent browser = ExperimentBrowserGrid.create(viewContext); + return createTab(Dict.EXPERIMENT_BROWSER, browser); + } + + public String getId() + { + return ExperimentBrowserGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getPropertyTypeBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = PropertyTypeGrid.create(viewContext); + return createTab(Dict.PROPERTY_TYPES, component); + } + + public String getId() + { + return PropertyTypeGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getPropertyTypeRegistration() + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new PropertyTypeRegistrationForm(viewContext); + return createTab(Dict.PROPERTY_TYPE_REGISTRATION, component, true); + } + + public String getId() + { + return PropertyTypeRegistrationForm.ID; + } + }; + } + + public ITabItemFactory getPropertyTypeAssignmentBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = PropertyTypeAssignmentGrid.create(viewContext); + return createTab(Dict.PROPERTY_TYPE_ASSIGNMENTS, component); + } + + public String getId() + { + return PropertyTypeAssignmentGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getPropertyTypeExperimentTypeAssignmentForm() + { + return getPropertyTypeAssignmentForm(EntityKind.EXPERIMENT, + Dict.ASSIGN_EXPERIMENT_PROPERTY_TYPE); + } + + public ITabItemFactory getPropertyTypeMaterialTypeAssignmentForm() + { + return getPropertyTypeAssignmentForm(EntityKind.MATERIAL, + Dict.ASSIGN_MATERIAL_PROPERTY_TYPE); + } + + public ITabItemFactory getPropertyTypeDataSetTypeAssignmentForm() + { + return getPropertyTypeAssignmentForm(EntityKind.DATA_SET, + Dict.ASSIGN_DATA_SET_PROPERTY_TYPE); + } + + public ITabItemFactory getPropertyTypeSampleTypeAssignmentForm() + { + return getPropertyTypeAssignmentForm(EntityKind.SAMPLE, Dict.ASSIGN_SAMPLE_PROPERTY_TYPE); + } + + private ITabItemFactory getPropertyTypeAssignmentForm(final EntityKind entityKind, + final String messageKey) + { + return new ITabItemFactory() + { + public ITabItem create() + { + Component component = new PropertyTypeAssignmentForm(viewContext, entityKind); + return new DefaultTabItem(getMessage(messageKey), component, true); + } + + public String getId() + { + return PropertyTypeAssignmentForm.createId(entityKind); + } + }; + } + + public ITabItemFactory getDataSetSearch() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent browser = DataSetSearchHitGrid.create(viewContext); + return createTab(Dict.DATA_SET_SEARCH, browser); + } + + public String getId() + { + return DataSetSearchHitGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getSampleTypeBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = SampleTypeGrid.create(viewContext); + return createTab(Dict.SAMPLE_TYPES, component); + } + + public String getId() + { + return SampleTypeGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getMaterialTypeBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = MaterialTypeGrid.create(viewContext); + return createTab(Dict.MATERIAL_TYPES, component); + } + + public String getId() + { + return MaterialTypeGrid.BROWSER_ID; + } + }; + } + + public ITabItemFactory getExperimentTypeBrowser() + { + return new ITabItemFactory() + { + public ITabItem create() + { + DisposableComponent component = ExperimentTypeGrid.create(viewContext); + return createTab(Dict.EXPERIMENT_TYPES, component); + } + + public String getId() + { + return ExperimentTypeGrid.BROWSER_ID; + } + }; + } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java index 6dfbaf3e082..bce900ee1c6 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ContentPanelAdapter.java @@ -16,8 +16,6 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; -import com.extjs.gxt.ui.client.event.Listener; -import com.extjs.gxt.ui.client.event.TabPanelEvent; import com.extjs.gxt.ui.client.widget.Component; import com.extjs.gxt.ui.client.widget.ContentPanel; import com.extjs.gxt.ui.client.widget.Header; @@ -33,23 +31,14 @@ public final class ContentPanelAdapter implements ITabItem { private final ContentPanel contentPanel; - private final Listener<TabPanelEvent> tabPanelEventListener; - private final boolean isCloseConfirmationNeeded; public ContentPanelAdapter(final ContentPanel contentPanel, boolean isCloseConfirmationNeeded) - { - this(contentPanel, isCloseConfirmationNeeded, null); - } - - public ContentPanelAdapter(final ContentPanel contentPanel, boolean isCloseConfirmationNeeded, - final Listener<TabPanelEvent> tabPanelEventListener) { // Note that if not set, is then automatically generated. So this is why we test for // 'ID_PREFIX'. We want the user to set an unique id. assert contentPanel.getId().startsWith(GenericConstants.ID_PREFIX) : "Unspecified component id."; this.contentPanel = contentPanel; - this.tabPanelEventListener = tabPanelEventListener; this.isCloseConfirmationNeeded = isCloseConfirmationNeeded; } @@ -78,13 +67,18 @@ public final class ContentPanelAdapter implements ITabItem // Does nothing. } - public final Listener<TabPanelEvent> tryGetEventListener() + public boolean isCloseConfirmationNeeded() { - return tabPanelEventListener; + return isCloseConfirmationNeeded; } - public boolean isCloseConfirmationNeeded() + public void onActivate() { - return isCloseConfirmationNeeded; + // TODO 2009-03-26, Tomasz Pylak: add refresh on db modifications support + } + + public void onClose() + { + // do nothing } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java index 4a1e7d96fa9..37e36fa5fcf 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DefaultTabItem.java @@ -16,12 +16,12 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; -import com.extjs.gxt.ui.client.Events; -import com.extjs.gxt.ui.client.event.Listener; -import com.extjs.gxt.ui.client.event.TabPanelEvent; + import com.extjs.gxt.ui.client.widget.Component; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableComponent; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction; /** * A default {@link ITabItem} implementation. @@ -34,48 +34,52 @@ public class DefaultTabItem implements ITabItem private final Component component; - private final Listener<TabPanelEvent> tabPanelEventListener; + private final IDelegatedAction disposerActionOrNull; private final boolean isCloseConfirmationNeeded; + private final LastModificationStateUpdater lastModificationStateUpdaterOrNull; + + // TODO 2009-03-26, Tomasz Pylak: add Database Modification Observer public DefaultTabItem(final String title, final Component component, boolean isCloseConfirmationNeeded) { - this(title, component, isCloseConfirmationNeeded, null); + this(title, component, null, null, isCloseConfirmationNeeded); } - public static ITabItem create(final String title, final DisposableComponent component) + public static ITabItem create(final String title, final DisposableComponent component, + IViewContext<?> viewContext) { boolean isCloseConfirmationNeeded = false; - Listener<TabPanelEvent> eventListener = createCloseEventListener(component); - return new DefaultTabItem(title, component.getComponent(), isCloseConfirmationNeeded, - eventListener); + LastModificationStateUpdater updater = + new LastModificationStateUpdater(viewContext, component); + IDelegatedAction disposer = createDisposer(component); + return new DefaultTabItem(title, component.getComponent(), updater, disposer, + isCloseConfirmationNeeded); } - private static Listener<TabPanelEvent> createCloseEventListener( - final DisposableComponent component) + private static IDelegatedAction createDisposer(final DisposableComponent disposableComponent) { - return new Listener<TabPanelEvent>() + return new IDelegatedAction() { - public final void handleEvent(final TabPanelEvent be) + public void execute() { - if (be.type == Events.Close) - { - component.dispose(); - } + disposableComponent.dispose(); } }; } private DefaultTabItem(final String title, final Component component, - boolean isCloseConfirmationNeeded, final Listener<TabPanelEvent> tabPanelEventListener) + LastModificationStateUpdater lastModificationStateUpdaterOrNull, + IDelegatedAction disposerActionOrNull, boolean isCloseConfirmationNeeded) { assert title != null : "Unspecified title."; assert component != null : "Unspecified component."; this.title = title; this.component = component; + this.lastModificationStateUpdaterOrNull = lastModificationStateUpdaterOrNull; + this.disposerActionOrNull = disposerActionOrNull; this.isCloseConfirmationNeeded = isCloseConfirmationNeeded; - this.tabPanelEventListener = tabPanelEventListener; } // @@ -92,13 +96,24 @@ public class DefaultTabItem implements ITabItem return title; } - public final Listener<TabPanelEvent> tryGetEventListener() + public boolean isCloseConfirmationNeeded() { - return tabPanelEventListener; + return isCloseConfirmationNeeded; } - public boolean isCloseConfirmationNeeded() + public void onActivate() { - return isCloseConfirmationNeeded; + if (lastModificationStateUpdaterOrNull != null) + { + lastModificationStateUpdaterOrNull.update(); + } + } + + public void onClose() + { + if (disposerActionOrNull != null) + { + disposerActionOrNull.execute(); + } } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java new file mode 100644 index 00000000000..d8a97a94ca6 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IDatabaseModificationObserver.java @@ -0,0 +1,42 @@ +/* + * Copyright 2009 ETH Zuerich, CISD + * + * Licensed 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. + */ + +package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; + +import java.util.Set; + +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; + +/** + * @author Tomasz Pylak + */ +public interface IDatabaseModificationObserver +{ + /** + * Informs about new modifications in the database. + * + * @param observedModifications The new database modifications which have occurred. This is a + * subset of the modifications in which this observer is interested. + */ + void update(Set<DatabaseModificationKind> observedModifications); + + /** + * @return the list of database object modifications in which this observer is interested. Used + * to call the refresh method only when it is really necessary. + */ + DatabaseModificationKind[] getRelevantModifications(); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java index ec61ef48ba5..b22bb776f78 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ITabItem.java @@ -16,8 +16,6 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; -import com.extjs.gxt.ui.client.event.Listener; -import com.extjs.gxt.ui.client.event.TabPanelEvent; import com.extjs.gxt.ui.client.widget.Component; import com.extjs.gxt.ui.client.widget.TabItem; @@ -41,10 +39,17 @@ public interface ITabItem */ public Component getComponent(); + /** Performs cleaning operations, should be called before the tab is closed. */ + public void onClose(); + /** - * Returns a {@link Listener} that should be registered to the tab item. + * Performs operations relevant to the tab when it is activated, namely when we opened this tab + * for the first time or we switched from another tab to this one. + * <p> + * Usually refreshes the tab if it was detected that relevant database objects have changed. + * </p> */ - public Listener<TabPanelEvent> tryGetEventListener(); + public void onActivate(); /** * Returns true if the confirmation dialog should be displayed before closing the tab. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java new file mode 100644 index 00000000000..d2024432c67 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/LastModificationStateUpdater.java @@ -0,0 +1,114 @@ +/* + * Copyright 2009 ETH Zuerich, CISD + * + * Licensed 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. + */ + +package ch.systemsx.cisd.openbis.generic.client.web.client.application.framework; + +import java.util.HashSet; +import java.util.Set; + +import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LastModificationState; + +/** + * Stores last database modification state and provides a method to update the state from the + * server. Informs a specified modification observer about relevant modifications. + * + * @author Tomasz Pylak + */ +class LastModificationStateUpdater extends AbstractAsyncCallback<LastModificationState> +{ + private final ICommonClientServiceAsync commonService; + + /* + * The last database objects modification state seen by this tab. Can be null only for a short + * period after the first tab activation when we are waiting for the server response. + */ + private LastModificationState lastSeenModificationStateOrNull; + + private final IDatabaseModificationObserver modificationObserver; + + public LastModificationStateUpdater(IViewContext<?> viewContext, + IDatabaseModificationObserver modificationObserver) + { + super(viewContext, false); + this.commonService = viewContext.getCommonService(); + this.modificationObserver = modificationObserver; + this.lastSeenModificationStateOrNull = null; + } + + private void debug(String msg) + { + // TODO 2009-03-26, Tomasz Pylak: add proper logging + System.out.println("LMS Updater: " + msg); + } + + public void update() + { + commonService.getLastModificationState(this); + } + + @Override + protected void process(LastModificationState freshState) + { + refreshIfNecessary(freshState); + updateState(freshState); + } + + private void refreshIfNecessary(LastModificationState freshState) + { + if (lastSeenModificationStateOrNull == null) + { + // this is the first activation, no refresh is needed + return; + } + DatabaseModificationKind[] relevantModifications = + modificationObserver.getRelevantModifications(); + Set<DatabaseModificationKind> unseenModifications = + extractUnseenModifications(relevantModifications, freshState, + lastSeenModificationStateOrNull); + if (unseenModifications.size() > 0) + { + debug("new modifications detected: " + unseenModifications); + modificationObserver.update(unseenModifications); + } + } + + // returns all new relevant modifications + private static Set<DatabaseModificationKind> extractUnseenModifications( + DatabaseModificationKind[] relevantModifications, LastModificationState freshState, + LastModificationState lastSeenModificationState) + { + Set<DatabaseModificationKind> unseenModifications = new HashSet<DatabaseModificationKind>(); + for (DatabaseModificationKind modification : relevantModifications) + { + long lastSeen = lastSeenModificationState.getLastModificationTime(modification); + long lastModification = freshState.getLastModificationTime(modification); + if (lastSeen < lastModification) + { + unseenModifications.add(modification); + } + } + return unseenModifications; + } + + private void updateState(LastModificationState freshState) + { + this.lastSeenModificationStateOrNull = freshState; + } +} \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java index 13c097a84b0..2cb916bbd72 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java @@ -128,16 +128,42 @@ public class MainTabPanel extends TabPanel setText(tabItem.getTabTitle()); addStyleName("pad-text"); add(tabItem.getComponent()); - final Listener<TabPanelEvent> tabPanelEventListener = tabItem.tryGetEventListener(); if (tabItem.isCloseConfirmationNeeded()) { addListener(Events.BeforeClose, createBeforeCloseListener(this, idPrefix)); } - if (tabPanelEventListener != null) - { - addListener(Events.Close, tabPanelEventListener); - } - addListener(Events.Close, createTabCloseListener(idPrefix)); + addListener(Events.Close, createCloseTabListener(tabItem, idPrefix)); + addListener(Events.Select, createActivateTabListener(tabItem)); + } + + private Listener<TabPanelEvent> createCloseTabListener(final ITabItem tabItem, + final String id) + { + return new Listener<TabPanelEvent>() + { + public final void handleEvent(final TabPanelEvent be) + { + if (be.type == Events.Close) + { + tabItem.onClose(); + openTabs.remove(id); + } + } + }; + } + + private Listener<TabPanelEvent> createActivateTabListener(final ITabItem tabItem) + { + return new Listener<TabPanelEvent>() + { + public final void handleEvent(final TabPanelEvent be) + { + if (be.type == Events.Select) + { + tabItem.onActivate(); + } + } + }; } private Listener<TabPanelEvent> createBeforeCloseListener(final MainTabItem mainTabItem, @@ -161,16 +187,5 @@ public class MainTabPanel extends TabPanel } }; } - - private Listener<TabPanelEvent> createTabCloseListener(final String id) - { - return new Listener<TabPanelEvent>() - { - public void handleEvent(final TabPanelEvent be) - { - openTabs.remove(id); - } - }; - } } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java index 1bc3380e203..20660ff3da5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractEntityTypeGrid.java @@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Ab import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.AddEntityTypeDialog; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; /** @@ -104,4 +105,11 @@ abstract public class AbstractEntityTypeGrid extends AbstractSimpleBrowserGrid<E return asColumnFilters(new EntityTypeColDefKind[] { EntityTypeColDefKind.CODE }); } + + public DatabaseModificationKind[] getRelevantModifications() + { + // grid is refreshed manually when a new type is added, so there can be no auto-refresh + return new DatabaseModificationKind[] {}; + } + } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java index 8a3eb6ca5e6..77d817f6023 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchHitGrid.java @@ -17,6 +17,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import java.util.List; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; @@ -33,7 +36,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * Grid with data set search results. @@ -119,4 +124,13 @@ public class DataSetSearchHitGrid extends AbstractExternalDataGrid return DataSetSearchHitModel.createColumnsSchema(viewContext, availablePropertyTypes); } + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.EXPERIMENT), + edit(ObjectKind.SAMPLE), + createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT), + createOrDelete(ObjectKind.VOCABULARY_TERM) }; + } + } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java index 06d8bb143d5..b4cfcbea9a2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java @@ -16,6 +16,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import java.util.List; import com.extjs.gxt.ui.client.event.SelectionChangedListener; @@ -49,6 +52,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCri import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; @@ -56,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * A {@link LayoutContainer} which contains the grid where the experiments are displayed. @@ -253,4 +258,14 @@ public class ExperimentBrowserGrid extends AbstractBrowserGrid<Experiment, Exper return asColumnFilters(new CommonExperimentColDefKind[] { CommonExperimentColDefKind.CODE }); } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.EXPERIMENT_TYPE), createOrDelete(ObjectKind.PROJECT), + createOrDelete(ObjectKind.SAMPLE), createOrDelete(ObjectKind.EXPERIMENT), + createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.SAMPLE), + edit(ObjectKind.EXPERIMENT), edit(ObjectKind.DATA_SET), + createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) }; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java index 020fcde0aac..15dce9c941d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import com.extjs.gxt.ui.client.Events; import com.extjs.gxt.ui.client.Style.SelectionMode; @@ -61,6 +62,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict; import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.VoidAsyncCallback; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver; import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils; @@ -75,12 +77,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SortInfo; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SortInfo.SortDir; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; /** * @author Tomasz Pylak */ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityModel<T>> extends - LayoutContainer + LayoutContainer implements IDatabaseModificationObserver { /** * Shows the detail view for the specified entity @@ -204,13 +207,24 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod add(contentPanel); } + // TODO 2009-03-26, Tomasz Pylak: delete this and implement in subclasses + // !!!!!!!!!!!!!!!!!!!!!!!!! + public void update(Set<DatabaseModificationKind> observedModifications) + { + System.out.println("grid refresh requested: " + observedModifications); + grid.setLoadMask(false); + refresh(); + grid.setLoadMask(true); + } + /** * Registers the specified listener for clicks on cells in the specified column. * * @param columnID Column ID. Not case sensitive. * @param listener Listener handle single clicks. */ - public void registerCellClickListenerFor(final String columnID, final ICellListener<T> listener) + protected void registerCellClickListenerFor(final String columnID, + final ICellListener<T> listener) { columnListener.registerCellClickListener(columnID, listener); } @@ -221,7 +235,8 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod * @param columnID Column ID. Not case sensitive. * @param listener Listener handle single clicks. */ - public void registerLinkClickListenerFor(final String columnID, final ICellListener<T> listener) + protected void registerLinkClickListenerFor(final String columnID, + final ICellListener<T> listener) { columnListener.registerLinkClickListener(columnID, listener); } @@ -229,7 +244,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod /** * Allows multiple selection instead of single selection. */ - public void allowMultipleSelection() + protected void allowMultipleSelection() { grid.getSelectionModel().setSelectionMode(SelectionMode.MULTI); } @@ -285,6 +300,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod private DisposableEntityChooser<T> asDisposableMaterialChooser(final Component mainComponent) { + final AbstractBrowserGrid<T, M> self = this; return new DisposableEntityChooser<T>() { public T tryGetSingleSelected() @@ -301,13 +317,23 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod public void dispose() { - disposeCache(); + self.disposeCache(); } public Component getComponent() { return mainComponent; } + + public DatabaseModificationKind[] getRelevantModifications() + { + return self.getRelevantModifications(); + } + + public void update(Set<DatabaseModificationKind> observedModifications) + { + self.update(observedModifications); + } }; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java index 9dd4eb88e49..69e46e494ca 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComponent.java @@ -18,12 +18,15 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid; import com.extjs.gxt.ui.client.widget.Component; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver; + /** * Component which should be disposed at the end of the life cycle * * @author Tomasz Pylak */ -public interface DisposableComponent +// TODO 2009-03-26, Tomasz Pylak: add 'I' prefix +public interface DisposableComponent extends IDatabaseModificationObserver { Component getComponent(); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java index b1cc9945f33..46af47f66f3 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialBrowserGrid.java @@ -16,6 +16,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import java.util.List; import com.extjs.gxt.ui.client.event.SelectionChangedListener; @@ -47,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Material; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; @@ -54,6 +58,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * A {@link LayoutContainer} which contains the grid where the materials are displayed. @@ -280,4 +285,11 @@ public class MaterialBrowserGrid extends AbstractBrowserGrid<Material, MaterialM + entity.getMaterialType().getCode() + ")", entity.getId(), entity .getModificationDate()); } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.MATERIAL_TYPE), createOrDelete(ObjectKind.MATERIAL), + edit(ObjectKind.MATERIAL) }; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java index 0a7a5aa9d57..2cc03e4d40d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java @@ -31,6 +31,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * Grid displaying projects. @@ -81,4 +83,10 @@ public class ProjectGrid extends AbstractSimpleBrowserGrid<Project> return asColumnFilters(new ProjectColDefKind[] { ProjectColDefKind.CODE, ProjectColDefKind.GROUP }); } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { DatabaseModificationKind.createOrDelete(ObjectKind.PROJECT) }; + } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java index 4e610bf675c..258ae254584 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java @@ -30,7 +30,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * Grid with 'entity type' - 'property type' assignments. @@ -87,4 +89,10 @@ public class PropertyTypeAssignmentGrid extends { viewContext.getService().prepareExportPropertyTypeAssignments(exportCriteria, callback); } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { DatabaseModificationKind.createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) }; + } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java index f8e931492e6..5eb1874c1c9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeGrid.java @@ -16,6 +16,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; + import java.util.List; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; @@ -31,7 +33,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * Grid displaying property types. @@ -89,4 +93,11 @@ public class PropertyTypeGrid extends AbstractSimpleBrowserGrid<PropertyType> { viewContext.getService().prepareExportPropertyTypes(exportCriteria, callback); } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.PROPERTY_TYPE), + createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) }; + } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java index a34af4950c3..02d4eafc032 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java @@ -16,6 +16,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import java.util.List; import com.extjs.gxt.ui.client.event.SelectionChangedListener; @@ -53,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Sample; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType; @@ -60,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * A {@link LayoutContainer} which contains the grid where the samples are displayed. @@ -305,4 +310,11 @@ public final class SampleBrowserGrid extends AbstractBrowserGrid<Sample, SampleM return criteria == null || sampleType != null && sampleType.equals(criteria.getSampleType()) == false; } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { edit(ObjectKind.SAMPLE), createOrDelete(ObjectKind.SAMPLE), + createOrDelete(ObjectKind.SAMPLE_TYPE), createOrDelete(ObjectKind.GROUP) }; + } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java index 528434bc434..e94c53663f4 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyGrid.java @@ -42,7 +42,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** * Grid displaying vocabularies. @@ -128,7 +130,7 @@ public class VocabularyGrid extends AbstractSimpleBrowserGrid<Vocabulary> String tabTitle = viewContext.getMessage(Dict.VOCABULARY_TERMS_BROWSER, vocabulary .getCode()); - return DefaultTabItem.create(tabTitle, component); + return DefaultTabItem.create(tabTitle, component, viewContext); } public String getId() @@ -139,4 +141,10 @@ public class VocabularyGrid extends AbstractSimpleBrowserGrid<Vocabulary> DispatcherHelper.dispatchNaviEvent(tabFactory); } + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { DatabaseModificationKind.createOrDelete(ObjectKind.VOCABULARY) }; + } + } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java index e9be171d6f1..1108808152e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyTermGrid.java @@ -57,6 +57,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IColumnDefinition; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.VocabularyTermWithStats; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermReplacement; @@ -108,7 +109,8 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm } }); pagingToolbar.add(new AdapterToolItem(addButton)); - Button deleteButton = new Button(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_BUTTON)); + Button deleteButton = + new Button(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_BUTTON)); deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>() { @Override @@ -158,12 +160,13 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm } @Override - protected void prepareExportEntities(TableExportCriteria<VocabularyTermWithStats> exportCriteria, + protected void prepareExportEntities( + TableExportCriteria<VocabularyTermWithStats> exportCriteria, AbstractAsyncCallback<String> callback) { viewContext.getService().prepareExportVocabularyTerms(exportCriteria, callback); } - + private void askForNewTerms() { final TextArea textArea = new TextArea(); @@ -200,7 +203,13 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm dialog.setEnableOfAcceptButton(false); dialog.show(); } - + + public DatabaseModificationKind[] getRelevantModifications() + { + // grid is refreshed manually when a new object is added, so there can be no auto-refresh + return new DatabaseModificationKind[] {}; + } + private void deleteTerms() { List<BaseEntityModel<VocabularyTermWithStats>> terms = getSelectedItems(); @@ -210,14 +219,14 @@ public class VocabularyTermGrid extends AbstractSimpleBrowserGrid<VocabularyTerm } if (terms.size() == vocabulary.getTerms().size()) { - MessageBox.alert( - viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_TITLE), + MessageBox.alert(viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_TITLE), viewContext.getMessage(Dict.DELETE_VOCABULARY_TERMS_INVALID_MESSAGE), null); return; } Set<String> selectedTerms = new HashSet<String>(); List<VocabularyTerm> termsToBeDeleted = new ArrayList<VocabularyTerm>(); - List<VocabularyTermReplacement> termsToBeReplaced = new ArrayList<VocabularyTermReplacement>(); + List<VocabularyTermReplacement> termsToBeReplaced = + new ArrayList<VocabularyTermReplacement>(); for (BaseEntityModel<VocabularyTermWithStats> model : terms) { VocabularyTerm term = model.getBaseObject().getTerm(); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java index 96ce2beca41..1d75125248f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DatabaseLastModificationAdvisor.java @@ -137,7 +137,7 @@ public final class DatabaseLastModificationAdvisor extends DefaultPointcutAdviso } for (ObjectKind objectKind : annotation.value()) { - categories.add(DatabaseModificationKind.createUpdate(objectKind)); + categories.add(DatabaseModificationKind.edit(objectKind)); } } @@ -152,7 +152,7 @@ public final class DatabaseLastModificationAdvisor extends DefaultPointcutAdviso } for (ObjectKind objectKind : annotation.value()) { - categories.add(DatabaseModificationKind.createNew(objectKind)); + categories.add(DatabaseModificationKind.createOrDelete(objectKind)); } } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java index ebc941b0a2b..b4aa3e9fc8d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java @@ -306,6 +306,7 @@ public interface ICommonServer extends IServer */ @Transactional @RolesAllowed(RoleSet.INSTANCE_ADMIN) + @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM) public void addVocabularyTerms(String sessionToken, String vocabularyCode, List<String> vocabularyTerms); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java index 27b7e7834ab..e823e8196dc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/DatabaseModificationKind.java @@ -44,21 +44,22 @@ public class DatabaseModificationKind implements IsSerializable private OperationKind operationKind; // GWT only + @SuppressWarnings("unused") private DatabaseModificationKind() { } - public static final DatabaseModificationKind createNew(ObjectKind objectType) + public static final DatabaseModificationKind createOrDelete(ObjectKind objectType) { return new DatabaseModificationKind(objectType, OperationKind.CREATE_OR_DELETE); } - public static final DatabaseModificationKind createUpdate(ObjectKind objectType) + public static final DatabaseModificationKind edit(ObjectKind objectType) { return new DatabaseModificationKind(objectType, OperationKind.UPDATE); } - private DatabaseModificationKind(ObjectKind objectType, OperationKind operationKind) + public DatabaseModificationKind(ObjectKind objectType, OperationKind operationKind) { this.objectType = objectType; this.operationKind = operationKind; @@ -74,6 +75,23 @@ public class DatabaseModificationKind implements IsSerializable return operationKind; } + @Override + public boolean equals(Object obj) + { + if (obj == null || obj instanceof DatabaseModificationKind == false) + { + return false; + } + DatabaseModificationKind that = (DatabaseModificationKind) obj; + return objectType == that.objectType && operationKind == that.operationKind; + } + + @Override + public int hashCode() + { + return 17 * objectType.hashCode() + operationKind.hashCode(); + } + @Override public String toString() { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java index f73413ee29b..91607b40b15 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/LastModificationState.java @@ -33,9 +33,13 @@ public class LastModificationState implements IsSerializable { private Map<DatabaseModificationKind, Long/* timestamp */> state; + private long initializationTimestamp; + + /** Creates a state marking all */ public LastModificationState() { this.state = new HashMap<DatabaseModificationKind, Long>(); + this.initializationTimestamp = new Date().getTime(); } public synchronized void registerModification(DatabaseModificationKind kind, @@ -49,9 +53,24 @@ public class LastModificationState implements IsSerializable state.put(kind, currentTimestamp); } - public Long tryGetLastModification(DatabaseModificationKind kind) + /** + * To avoid expensive computation of the last modification time at the beginning (which would + * require browsing the whole database) at the beginning we assume that it's equal to the + * initialization time of the whole state. We can do this since all the future modifications + * will happen after this moment. + * + * @return The last registered time of the specified kind of database modification. + */ + public long getLastModificationTime(DatabaseModificationKind kind) { - return state.get(kind); + Long lastModification = state.get(kind); + if (lastModification == null) + { + return initializationTimestamp; + } else + { + return lastModification; + } } @Override diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java index 9eab16675aa..9c1a2f11330 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentDataSetBrowser.java @@ -16,6 +16,9 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.createOrDelete; +import static ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.edit; + import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback; import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants; @@ -26,10 +29,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** - * - * * @author Franz-Josef Elmer */ public class ExperimentDataSetBrowser extends AbstractExternalDataGrid @@ -37,12 +40,14 @@ public class ExperimentDataSetBrowser extends AbstractExternalDataGrid private static final String PREFIX = "experiment-data-section_"; public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX; - + static DisposableComponent create(IViewContext<?> viewContext, Experiment experiment) { - IViewContext<ICommonClientServiceAsync> commonViewContext = viewContext.getCommonViewContext(); + IViewContext<ICommonClientServiceAsync> commonViewContext = + viewContext.getCommonViewContext(); String identifier = experiment.getIdentifier(); - return new ExperimentDataSetBrowser(commonViewContext, identifier).asDisposableWithoutToolbar(); + return new ExperimentDataSetBrowser(commonViewContext, identifier) + .asDisposableWithoutToolbar(); } private final String experimentIdentifier; @@ -58,7 +63,15 @@ public class ExperimentDataSetBrowser extends AbstractExternalDataGrid protected void listEntities(DefaultResultSetConfig<String, ExternalData> resultSetConfig, AbstractAsyncCallback<ResultSet<ExternalData>> callback) { - viewContext.getService().listExperimentDataSets(experimentIdentifier, resultSetConfig, callback); + viewContext.getService().listExperimentDataSets(experimentIdentifier, resultSetConfig, + callback); + } + + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { createOrDelete(ObjectKind.DATA_SET), edit(ObjectKind.DATA_SET), + createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT) }; } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java index ba2b47c2378..6c79f9bf3f2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SampleDataSetBrowser.java @@ -24,21 +24,23 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Di import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind; /** - * - * * @author Franz-Josef Elmer */ class SampleDataSetBrowser extends AbstractExternalDataGrid { - static DisposableComponent create(IViewContext<?> viewContext, String sampleIdentifier, String browserID) + static DisposableComponent create(IViewContext<?> viewContext, String sampleIdentifier, + String browserID) { IViewContext<ICommonClientServiceAsync> commonViewContext = viewContext.getCommonViewContext(); return new SampleDataSetBrowser(commonViewContext, sampleIdentifier, browserID) .asDisposableWithoutToolbar(); } + private final String sampleIdentifier; private SampleDataSetBrowser(IViewContext<ICommonClientServiceAsync> viewContext, @@ -55,4 +57,11 @@ class SampleDataSetBrowser extends AbstractExternalDataGrid viewContext.getService().listSampleDataSets(sampleIdentifier, resultSetConfig, callback); } + public DatabaseModificationKind[] getRelevantModifications() + { + return new DatabaseModificationKind[] + { DatabaseModificationKind.createOrDelete(ObjectKind.SAMPLE), + DatabaseModificationKind.edit(ObjectKind.SAMPLE) }; + } + } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected index de6286f6d49..ebaa7f07016 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected @@ -306,14 +306,18 @@ public interface ICommonServer extends IServer */ @Transactional @RolesAllowed(RoleSet.INSTANCE_ADMIN) + @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM) public void addVocabularyTerms(String sessionToken, String vocabularyCode, List<String> vocabularyTerms); + /** + * Deletes from the specified vocabulary the specified terms. + */ @Transactional @RolesAllowed(RoleSet.INSTANCE_ADMIN) public void deleteVocabularyTerms(String sessionToken, String vocabularyCode, List<VocabularyTerm> termsToBeDeleted, List<VocabularyTermReplacement> termsToBeReplaced); - + /** * Registers new project. */ -- GitLab