diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index 7bd6a13610a7a8574f4aa683b4fb0ec3fd6c25a0..f32262e11da25ef650d363635c418282e45b9432 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -318,17 +318,20 @@ public interface ICommonClientService extends IClientService
      * Registers given {@link Vocabulary}.
      */
     public void registerVocabulary(final Vocabulary vocabulary) throws UserFailureException;
-	
-	/** Adds specified terms to the specified vocabulary. */
+
+    /** Adds specified terms to the specified vocabulary. */
     public void addVocabularyTerms(String vocabularyCode, List<String> vocabularyTerms)
             throws UserFailureException;
-    
+
     /**
-     * Deletes the specified terms of the specified vocabulary. Terms in use will be replaced. 
+     * Deletes the specified terms of the specified vocabulary. Terms in use will be replaced.
      */
     public void deleteVocabularyTerms(String vocabularyCode, List<VocabularyTerm> termsToBeDeleted,
             List<VocabularyTermReplacement> termsToBeReplaced) throws UserFailureException;
-    
+
+    /** Lists terms of a specified vocabulary */
+    public List<VocabularyTerm> listVocabularyTerms(Vocabulary vocabulary);
+
     /**
      * Registers given {@link Project}.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index a3267b5828d39ceea03de44d4e60fad01da32924..d5292bc55bea3e70739cfa85c8edd37810b82833 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -283,7 +283,11 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     /** @see ICommonClientService#deleteVocabularyTerms(String, List, List) */
     public void deleteVocabularyTerms(String vocabularyCode, List<VocabularyTerm> termsToBeDeleted,
             List<VocabularyTermReplacement> termsToBeReplaced, AsyncCallback<Void> callback);
-    
+
+    /** @see ICommonClientService#listVocabularyTerms(Vocabulary) */
+    public void listVocabularyTerms(Vocabulary vocabulary,
+            AsyncCallback<List<VocabularyTerm>> callback);
+
     /** @see ICommonClientService#registerProject(Project) */
     public void registerProject(Project project,
             final AsyncCallback<Void> projectRegistrationCallback);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchableEntitySelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchableEntitySelectionWidget.java
index a7f41029eb1bf5ab98ba7fd29e37f5c15b9223e0..335300df7e1299d73718b4106694b7745a543a2e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchableEntitySelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/SearchableEntitySelectionWidget.java
@@ -26,6 +26,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Mode
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.SearchableEntityModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SearchableEntity;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 
 /**
  * A {@link ComboBox} extension for searching entities.
@@ -88,4 +89,8 @@ final class SearchableEntitySelectionWidget extends
                 .listSearchableEntities(new ListSearchableEntities(commonContext));
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.EMPTY_ARRAY;
+    }
 }
\ No newline at end of file
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 7bb8aa3e13081e7499f44305c510877fc919dc8e..7d7cbb91cf8940d08a1121ce205439a1e023c8ad 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
@@ -73,6 +73,13 @@ public final class ComponentProvider
         return DefaultTabItem.create(title, component, viewContext);
     }
 
+    // creates a tab which requires confirmation before it can be closed
+    private ITabItem createRegistrationTab(final String titleMessageKey,
+            DatabaseModificationAwareComponent component)
+    {
+        return DefaultTabItem.create(getMessage(titleMessageKey), component, viewContext, true);
+    }
+
     // TODO 2009-03-26, Tomasz Pylak: add db modification observer support
     private ITabItem createTab(String dictionaryMsgKey, Component component,
             boolean isCloseConfirmationNeeded)
@@ -186,8 +193,9 @@ public final class ComponentProvider
             {
                 public ITabItem create()
                 {
-                    Component component = new SampleRegistrationPanel(viewContext);
-                    return createTab(Dict.SAMPLE_REGISTRATION, component, true);
+                    DatabaseModificationAwareComponent component =
+                            SampleRegistrationPanel.create(viewContext);
+                    return createRegistrationTab(Dict.SAMPLE_REGISTRATION, component);
                 }
 
                 public String getId()
@@ -203,8 +211,9 @@ public final class ComponentProvider
             {
                 public ITabItem create()
                 {
-                    Component component = new ExperimentRegistrationPanel(viewContext);
-                    return createTab(Dict.EXPERIMENT_REGISTRATION, component, true);
+                    DatabaseModificationAwareComponent component =
+                            ExperimentRegistrationPanel.create(viewContext);
+                    return createRegistrationTab(Dict.EXPERIMENT_REGISTRATION, component);
                 }
 
                 public String getId()
@@ -414,8 +423,9 @@ public final class ComponentProvider
             {
                 public ITabItem create()
                 {
-                    Component component = new PropertyTypeAssignmentForm(viewContext, entityKind);
-                    return new DefaultTabItem(getMessage(messageKey), component, true);
+                    DatabaseModificationAwareComponent component =
+                            PropertyTypeAssignmentForm.create(viewContext, entityKind);
+                    return createRegistrationTab(messageKey, component);
                 }
 
                 public String getId()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CompositeDatabaseModificationObserver.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CompositeDatabaseModificationObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a49ee4b543437c1c42d14d929d2f9f5d5d93d67
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/CompositeDatabaseModificationObserver.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.SetUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * Composite class to implement {@link IDatabaseModificationObserver} interface for a collection of
+ * observers.
+ * 
+ * @author Tomasz Pylak
+ */
+public class CompositeDatabaseModificationObserver implements IDatabaseModificationObserver
+{
+    private final List<IDatabaseModificationObserver> registeredObservers;
+
+    public CompositeDatabaseModificationObserver()
+    {
+        this.registeredObservers = new ArrayList<IDatabaseModificationObserver>();
+    }
+
+    public void addObservers(List<? extends IDatabaseModificationObserver> observers)
+    {
+        for (IDatabaseModificationObserver observer : observers)
+        {
+            addObserver(observer);
+        }
+    }
+
+    public void addObserver(IDatabaseModificationObserver observer)
+    {
+        registeredObservers.add(observer);
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        List<DatabaseModificationKind> relevantModifications =
+                new ArrayList<DatabaseModificationKind>();
+        for (IDatabaseModificationObserver observer : registeredObservers)
+        {
+            SetUtils.addAll(relevantModifications, observer.getRelevantModifications());
+        }
+        return relevantModifications.toArray(DatabaseModificationKind.EMPTY_ARRAY);
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        for (IDatabaseModificationObserver observer : registeredObservers)
+        {
+            if (SetUtils.containsAny(observedModifications, observer.getRelevantModifications()))
+            {
+                observer.update(observedModifications);
+            }
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareComponent.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c394d116f2d722a8f93b6b666026e54b5b25b075
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareComponent.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.extjs.gxt.ui.client.widget.Component;
+
+/**
+ * Component which is aware of database modifications.
+ * 
+ * @author Tomasz Pylak
+ */
+public class DatabaseModificationAwareComponent extends DatabaseModificationAwareObject<Component>
+{
+    public DatabaseModificationAwareComponent(Component holder,
+            IDatabaseModificationObserver modificationObserver)
+    {
+        super(holder, modificationObserver);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareField.java
new file mode 100644
index 0000000000000000000000000000000000000000..87ad8a99aef331d4aa10fda04c2b7b384c1f8f5c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareField.java
@@ -0,0 +1,43 @@
+/*
+ * 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 com.extjs.gxt.ui.client.widget.form.Field;
+
+/**
+ * A field which is aware of database modifications.
+ * 
+ * @author Tomasz Pylak
+ */
+public class DatabaseModificationAwareField<T> extends DatabaseModificationAwareObject<Field<T>>
+{
+    /**
+     * Creates a mock with a dummy database modification observer. Use this method if your field
+     * does not need to be refreshed when the database changes.
+     */
+    public static <T> DatabaseModificationAwareField<T> wrapUnaware(Field<T> field)
+    {
+        return new DatabaseModificationAwareField<T>(field, createDummyModificationObserver());
+    }
+
+    public DatabaseModificationAwareField(Field<T> holder,
+            IDatabaseModificationObserver modificationObserver)
+    {
+        super(holder, modificationObserver);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareObject.java
new file mode 100644
index 0000000000000000000000000000000000000000..4977e7640545f9e5301936cceea37a215464db19
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareObject.java
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+/**
+ * Stores an object and its database modification observer.
+ * <p>
+ * This class is useful when you cannot modify some class T to extend
+ * {@link IDatabaseModificationObserver} interface (because e.g. this class comes from a library).
+ * </p>
+ * 
+ * @author Tomasz Pylak
+ */
+public class DatabaseModificationAwareObject<T> implements IDatabaseModificationObserver
+{
+    private final T object;
+
+    private final IDatabaseModificationObserver modificationObserver;
+
+    public static <T> DatabaseModificationAwareObject<T> createUnaware(T object)
+    {
+        IDatabaseModificationObserver dummyObserver = createDummyModificationObserver();
+        return new DatabaseModificationAwareObject<T>(object, dummyObserver);
+    }
+
+    protected static IDatabaseModificationObserver createDummyModificationObserver()
+    {
+        return new IDatabaseModificationObserver()
+            {
+
+                public DatabaseModificationKind[] getRelevantModifications()
+                {
+                    return DatabaseModificationKind.EMPTY_ARRAY;
+                }
+
+                public void update(Set<DatabaseModificationKind> observedModifications)
+                {
+                    // do nothing
+                }
+
+            };
+    }
+
+    public DatabaseModificationAwareObject(T holder,
+            IDatabaseModificationObserver modificationObserver)
+    {
+        this.object = holder;
+        this.modificationObserver = modificationObserver;
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return modificationObserver.getRelevantModifications();
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        modificationObserver.update(observedModifications);
+    }
+
+    /** @return the stored object */
+    public T get()
+    {
+        return object;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareWidget.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8bec91ac2a95f70e7535077c2bdebbd251aecf7
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DatabaseModificationAwareWidget.java
@@ -0,0 +1,43 @@
+/*
+ * 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 com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Widget which is aware of database modifications.
+ * 
+ * @author Tomasz Pylak
+ */
+public class DatabaseModificationAwareWidget extends DatabaseModificationAwareObject<Widget>
+{
+    /**
+     * Creates a mock with a dummy database modification observer. Use this method if your field
+     * does not need to be refreshed when the database changes.
+     */
+    public static DatabaseModificationAwareWidget wrapUnaware(Widget widget)
+    {
+        return new DatabaseModificationAwareWidget(widget, createDummyModificationObserver());
+    }
+
+    public DatabaseModificationAwareWidget(Widget holder,
+            IDatabaseModificationObserver modificationObserver)
+    {
+        super(holder, modificationObserver);
+    }
+
+}
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 37e36fa5fcf37b7c34b96d6f7e41a39207426e3f..9d1d7eb798a17352b6ce27ad8c904169884148c0 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,7 +16,6 @@
 
 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.IViewContext;
@@ -47,17 +46,34 @@ public class DefaultTabItem implements ITabItem
         this(title, component, null, null, isCloseConfirmationNeeded);
     }
 
+    public static ITabItem create(final String title,
+            final DatabaseModificationAwareComponent component, IViewContext<?> viewContext,
+            boolean isCloseConfirmationNeeded)
+    {
+        return create(title, component.get(), viewContext, component, null,
+                isCloseConfirmationNeeded);
+    }
+
     public static ITabItem create(final String title, final DisposableComponent component,
             IViewContext<?> viewContext)
     {
         boolean isCloseConfirmationNeeded = false;
-        LastModificationStateUpdater updater =
-                new LastModificationStateUpdater(viewContext, component);
         IDelegatedAction disposer = createDisposer(component);
-        return new DefaultTabItem(title, component.getComponent(), updater, disposer,
+        return create(title, component.getComponent(), viewContext, component, disposer,
                 isCloseConfirmationNeeded);
     }
 
+    private static DefaultTabItem create(final String title, final Component component,
+            IViewContext<?> viewContext, IDatabaseModificationObserver modificationObserver,
+            IDelegatedAction disposerActionOrNull, boolean isCloseConfirmationNeeded)
+    {
+        LastModificationStateUpdater updater =
+                new LastModificationStateUpdater(viewContext, modificationObserver);
+        return new DefaultTabItem(title, component, updater, disposerActionOrNull,
+                isCloseConfirmationNeeded);
+
+    }
+
     private static IDelegatedAction createDisposer(final DisposableComponent disposableComponent)
     {
         return new IDelegatedAction()
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
index d8a97a94ca680f05377be0140825c6c5f8a39261..e1a5af9fd35ebac07a21e51934946a0ea499d500 100644
--- 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
@@ -26,10 +26,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKin
 public interface IDatabaseModificationObserver
 {
     /**
-     * Informs about new modifications in the database.
+     * Informs about new modifications in the database. This method is called only if at least one
+     * observed modification is the relevant one.
      * 
-     * @param observedModifications The new database modifications which have occurred. This is a
-     *            subset of the modifications in which this observer is interested.
+     * @param observedModifications The new database modifications which have occurred.
      */
     void update(Set<DatabaseModificationKind> observedModifications);
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/ClientPluginAdapter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/ClientPluginAdapter.java
index f6a6d16f4020a3b9fa8ee2e85c0c20ec493b7f15..53e666943d8543bb814d4a90dbc81eaa19018ae5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/ClientPluginAdapter.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/ClientPluginAdapter.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin;
 
 import com.google.gwt.user.client.ui.Widget;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItemFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.IEditableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
@@ -49,7 +50,7 @@ public class ClientPluginAdapter<E extends EntityType, S extends EntityTypePrope
         throw new UnsupportedOperationException("Not yet implemented.");
     }
 
-    public Widget createRegistrationForEntityType(final E entityType)
+    public DatabaseModificationAwareWidget createRegistrationForEntityType(final E entityType)
     {
         throw new UnsupportedOperationException("Not yet implemented.");
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/IClientPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/IClientPlugin.java
index 8e805c69d80f7d686d5bda6a02686d263561f05b..d98a21b75ee0ca3cbbacab7260714c25a5239bd3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/IClientPlugin.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/plugin/IClientPlugin.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin;
 
 import com.google.gwt.user.client.ui.Widget;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItemFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.IEditableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdentifierHolder;
@@ -47,7 +48,7 @@ public interface IClientPlugin<T extends EntityType, S extends EntityTypePropert
     /**
      * Shows a registration form for entities of given <var>entityType</var>.
      */
-    public Widget createRegistrationForEntityType(final T entityType);
+    public DatabaseModificationAwareWidget createRegistrationForEntityType(final T entityType);
 
     /**
      * Shows a batch registration form for entities of given <var>entityType</var>.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
index 11eb52b5fd7b5a9aa36b03c45c28aa195e1da405..143a5912a43d2e80838f2415e449c8ea32a49cb4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/GroupSelectionWidget.java
@@ -31,6 +31,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.User;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of groups loaded from the server.
@@ -145,6 +147,10 @@ public final class GroupSelectionWidget extends DropDownList<GroupModel, Group>
     protected void loadData(AbstractAsyncCallback<List<Group>> callback)
     {
         viewContext.getCommonService().listGroups(null, new ListGroupsCallback(viewContext));
-
+    }
+    
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.GROUP);
     }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java
index ac6f4de5f05e9e1adbd33fe5c2c7e11cd70fabdc..5eae8a05bf997f02f10b9f589c0926b0894d5cca 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetSearchFieldsSelectionWidget.java
@@ -20,6 +20,9 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.widget.form.ComboBox;
+
 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.Dict;
@@ -32,11 +35,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchField;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetSearchFieldKind;
+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.PropertyType;
-
-import com.extjs.gxt.ui.client.store.ListStore;
-import com.extjs.gxt.ui.client.widget.form.ComboBox;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of search fields loaded from the server (property types) and
@@ -306,4 +308,9 @@ public final class DataSetSearchFieldsSelectionWidget extends
                     new ListPropertyTypesCallback(viewContext));
         }
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.PROPERTY_TYPE);
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetTypeSelectionWidget.java
index 53cafc3c3b265a817996f6e1ec4347baef30b703..8fae71ae861e32ac14600e2e85c86382d527acd0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetTypeSelectionWidget.java
@@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data;
 
 import java.util.List;
 
+import com.extjs.gxt.ui.client.widget.form.ComboBox;
+
 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.Dict;
@@ -26,44 +28,52 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Data
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
-
-import com.extjs.gxt.ui.client.widget.form.ComboBox;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of data set types loaded from the server.
  * 
  * @author Izabela Adamczyk
  */
-public final class DataSetTypeSelectionWidget extends
-		DropDownList<DataSetTypeModel, DataSetType> {
-	public static final String SUFFIX = "data-set-type";
+public final class DataSetTypeSelectionWidget extends DropDownList<DataSetTypeModel, DataSetType>
+{
+    public static final String SUFFIX = "data-set-type";
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
 
-	private final IViewContext<ICommonClientServiceAsync> viewContext;
+    public DataSetTypeSelectionWidget(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final String idSuffix)
+    {
+        super(viewContext, SUFFIX + idSuffix, Dict.DATA_SET_TYPE, ModelDataPropertyNames.CODE,
+                "data set type", "data set types");
+        this.viewContext = viewContext;
+    }
 
-	public DataSetTypeSelectionWidget(
-			final IViewContext<ICommonClientServiceAsync> viewContext,
-			final String idSuffix) {
-		super(viewContext, SUFFIX + idSuffix, Dict.DATA_SET_TYPE,
-				ModelDataPropertyNames.CODE, "data set type", "data set types");
-		this.viewContext = viewContext;
-	}
+    /**
+     * Returns the {@link DataSetType} currently selected.
+     * 
+     * @return <code>null</code> if nothing is selected yet.
+     */
+    public final DataSetType tryGetSelectedDataSetType()
+    {
+        return super.tryGetSelected();
+    }
 
-	/**
-	 * Returns the {@link DataSetType} currently selected.
-	 * 
-	 * @return <code>null</code> if nothing is selected yet.
-	 */
-	public final DataSetType tryGetSelectedDataSetType() {
-		return super.tryGetSelected();
-	}
+    @Override
+    protected List<DataSetTypeModel> convertItems(List<DataSetType> result)
+    {
+        return DataSetTypeModel.convert(result);
+    }
 
-	@Override
-	protected List<DataSetTypeModel> convertItems(List<DataSetType> result) {
-		return DataSetTypeModel.convert(result);
-	}
+    @Override
+    protected void loadData(AbstractAsyncCallback<List<DataSetType>> callback)
+    {
+        viewContext.getService().listDataSetTypes(callback);
+    }
 
-	@Override
-	protected void loadData(AbstractAsyncCallback<List<DataSetType>> callback) {
-		viewContext.getService().listDataSetTypes(callback);
-	}
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.DATASET_TYPE);
+    }
 }
\ 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 b4cfcbea9a298fa6943efcfbaef73a7e8ecb5d7d..7ae930dbfb88ca4a391777b3e9d40b2bb22b6f38 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
@@ -19,7 +19,10 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experi
 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.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
@@ -44,6 +47,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 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.DisposableEntityChooser;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.SetUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
@@ -261,11 +265,30 @@ public class ExperimentBrowserGrid extends AbstractBrowserGrid<Experiment, Exper
 
     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) };
+        List<DatabaseModificationKind> relevantModifications =
+                new ArrayList<DatabaseModificationKind>();
+        SetUtils.addAll(relevantModifications, topToolbar.getRelevantModifications());
+        relevantModifications.addAll(getGridRelevantModifications());
+        return relevantModifications.toArray(DatabaseModificationKind.EMPTY_ARRAY);
     }
+
+    private static Set<DatabaseModificationKind> getGridRelevantModifications()
+    {
+        Set<DatabaseModificationKind> result = new HashSet<DatabaseModificationKind>();
+        result.add(createOrDelete(ObjectKind.EXPERIMENT));
+        result.add(edit(ObjectKind.EXPERIMENT));
+        result.add(createOrDelete(ObjectKind.PROPERTY_TYPE_ASSIGNMENT));
+        return result;
+    }
+
+    @Override
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        topToolbar.update(observedModifications);
+        if (SetUtils.containsAny(observedModifications, getGridRelevantModifications()))
+        {
+            refreshGridSilently();
+        }
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserToolbar.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserToolbar.java
index 64e3003d3aebbf5cc60552ae1ed8dd58020c137c..14640f93fc4a2a88066ea42266135a5c3cb7d527 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserToolbar.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserToolbar.java
@@ -16,6 +16,10 @@
 
 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 java.util.Set;
+
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
 import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
@@ -27,10 +31,13 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 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.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * The toolbar of experiment browser.
@@ -38,7 +45,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
  * @author Izabela Adamczyk
  * @author Christian Ribeaud
  */
-class ExperimentBrowserToolbar extends ToolBar
+class ExperimentBrowserToolbar extends ToolBar implements IDatabaseModificationObserver
 {
     public static final String ID = "experiment-browser-toolbar";
 
@@ -102,4 +109,21 @@ class ExperimentBrowserToolbar extends ToolBar
         super.onRender(parent, pos);
     }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { createOrDelete(ObjectKind.EXPERIMENT_TYPE), createOrDelete(ObjectKind.PROJECT) };
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        if (observedModifications.contains(createOrDelete(ObjectKind.EXPERIMENT_TYPE)))
+        {
+            selectExperimentTypeCombo.refreshStore();
+        }
+        if (observedModifications.contains(createOrDelete(ObjectKind.PROJECT)))
+        {
+            selectProjectCombo.refreshStore();
+        }
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentRegistrationPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentRegistrationPanel.java
index e214230804e9f5a6870c4f49d91bf8dfc86bf68e..8e6a77d898f5ac0d5d86a701fa897b2935869af5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentRegistrationPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentRegistrationPanel.java
@@ -1,22 +1,23 @@
 /*
-* Copyright 2008 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.
-*/
+ * Copyright 2008 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.ui.experiment;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ExperimentTypeModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.EntityRegistrationPanel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
@@ -32,10 +33,16 @@ public final class ExperimentRegistrationPanel extends
 
     public static final String ID = EntityRegistrationPanel.createId(EntityKind.EXPERIMENT);
 
-    public ExperimentRegistrationPanel(final CommonViewContext viewContext)
+    public static final DatabaseModificationAwareComponent create(
+            final CommonViewContext viewContext)
+    {
+        ExperimentRegistrationPanel panel = new ExperimentRegistrationPanel(viewContext);
+        return new DatabaseModificationAwareComponent(panel, panel);
+    }
+
+    private ExperimentRegistrationPanel(final CommonViewContext viewContext)
     {
         super(viewContext, EntityKind.EXPERIMENT, new ExperimentTypeSelectionWidget(viewContext,
                 EntityRegistrationPanel.createId(EntityKind.EXPERIMENT)));
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentTypeSelectionWidget.java
index 0c400efa275824481d5f7e2b7ff15a67ddbba941..723f34ee7ccbaa8164c6dbd68a77b2ec01711864 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentTypeSelectionWidget.java
@@ -27,7 +27,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ExperimentTypeModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of experiment types loaded from the server.
@@ -70,4 +72,9 @@ public final class ExperimentTypeSelectionWidget extends
     {
         viewContext.getService().listExperimentTypes(callback);
     }
+    
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.EXPERIMENT_TYPE);
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
index 1174e8c7dbd1a05d51433670336be6389f388ef6..4867610bb701fcbeea34aa624b4c80a7af4a36e0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ProjectSelectionWidget.java
@@ -34,6 +34,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetCo
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Group;
 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.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of projects loaded from the server.
@@ -187,4 +189,10 @@ public final class ProjectSelectionWidget extends
         GWTUtils
                 .setSelectedItem(this, ModelDataPropertyNames.PROJECT_IDENTIFIER, projectIdentifier);
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.PROJECT);
+    }
+
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/PropertyFieldFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/PropertyFieldFactory.java
index 76acff7e1e9185e6e59dcdcd9163d4d8606b2a14..ca34e6faef2239c04c3d4f1d226317cf0b0559cf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/PropertyFieldFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/PropertyFieldFactory.java
@@ -22,6 +22,7 @@ import com.extjs.gxt.ui.client.widget.form.Field;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.VocabularyTermModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.DateRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
@@ -32,47 +33,53 @@ public class PropertyFieldFactory
     /**
      * Creates a field for given data type.
      */
-    public static Field<?> createField(final PropertyType pt, boolean isMandatory, String label,
-            String fieldId, String originalRawValue,
+    public static DatabaseModificationAwareField<?> createField(final PropertyType pt,
+            boolean isMandatory, String label, String fieldId, String originalRawValue,
             IViewContext<ICommonClientServiceAsync> viewContext)
     {
-        final Field<?> field =
+        final DatabaseModificationAwareField<?> fieldHolder =
                 doCreateField(pt, isMandatory, label, fieldId, originalRawValue, viewContext);
+        Field<?> field = fieldHolder.get();
         field.setId(fieldId);
         if (originalRawValue != null)
         {
             setValue(field, originalRawValue);
         }
-        return field;
+        return fieldHolder;
     }
 
-    private static Field<?> doCreateField(final PropertyType pt, boolean isMandatory, String label,
-            String fieldId, String originalRawValue,
+    private static DatabaseModificationAwareField<?> doCreateField(final PropertyType pt,
+            boolean isMandatory, String label, String fieldId, String originalRawValue,
             IViewContext<ICommonClientServiceAsync> viewContext)
     {
         final DataTypeCode dataType = pt.getDataType().getCode();
         switch (dataType)
         {
             case BOOLEAN:
-                return new CheckBoxField(label, isMandatory);
+                return wrapUnaware(new CheckBoxField(label, isMandatory));
             case VARCHAR:
-                return new VarcharField(label, isMandatory);
+                return wrapUnaware(new VarcharField(label, isMandatory));
             case TIMESTAMP:
-                return new DateFormField(label, isMandatory);
+                return wrapUnaware(new DateFormField(label, isMandatory));
             case CONTROLLEDVOCABULARY:
-                return new VocabularyTermSelectionWidget(fieldId, label, pt.getVocabulary()
-                        .getTerms(), isMandatory);
+                return VocabularyTermSelectionWidget.create(fieldId, label, pt.getVocabulary(),
+                        isMandatory, viewContext);
             case INTEGER:
-                return new IntegerField(label, isMandatory);
+                return wrapUnaware(new IntegerField(label, isMandatory));
             case REAL:
-                return new RealField(label, isMandatory);
+                return wrapUnaware(new RealField(label, isMandatory));
             case MATERIAL:
-                return MaterialChooserField.create(label, isMandatory, pt.getMaterialType(),
-                        originalRawValue, viewContext);
+                return wrapUnaware(MaterialChooserField.create(label, isMandatory, pt
+                        .getMaterialType(), originalRawValue, viewContext));
         }
         throw new IllegalStateException("unknown enum " + dataType);
     }
 
+    private static DatabaseModificationAwareField<?> wrapUnaware(Field<?> field)
+    {
+        return DatabaseModificationAwareField.wrapUnaware(field);
+    }
+
     private static <T> void setValue(final Field<T> field, String originalRawValue)
     {
         field.setValue(field.getPropertyEditor().convertStringValue(originalRawValue));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
index 53c4607863377e08792e47db4811cd19b96403a8..da434ade147f35c712625863d89ab2c7687de634 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
@@ -19,17 +19,24 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field;
 import java.util.ArrayList;
 import java.util.List;
 
+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.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.VocabularyTermModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.SimpleDropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
+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.DatabaseModificationKind.ObjectKind;
 
 /**
  * @author Izabela Adamczyk
  */
-public class VocabularyTermSelectionWidget extends SimpleDropDownList<VocabularyTermModel, String>
+public class VocabularyTermSelectionWidget extends
+        SimpleDropDownList<VocabularyTermModel, VocabularyTerm>
 {
 
     private static final String CHOOSE_MSG = "Choose...";
@@ -38,18 +45,80 @@ public class VocabularyTermSelectionWidget extends SimpleDropDownList<Vocabulary
 
     private static final String EMPTY_MSG = "- No terms found -";
 
+    private final Vocabulary vocabularyOrNull;
+
+    private final IViewContext<?> viewContextOrNull;
+
+    /**
+     * Allows to choose one of the specified vocabulary's terms, is able to refresh the available
+     * terms by calling the server.
+     */
+    public static DatabaseModificationAwareField<VocabularyTermModel> create(String idSuffix,
+            String label, Vocabulary vocabulary, final boolean mandatory,
+            IViewContext<?> viewContext)
+    {
+        return new VocabularyTermSelectionWidget(idSuffix, label, vocabulary.getTerms(), mandatory,
+                vocabulary, viewContext).asDatabaseModificationAware();
+    }
+
+    /**
+     * Allows to choose one of the specified vocabulary terms.
+     */
     public VocabularyTermSelectionWidget(String idSuffix, String label, List<VocabularyTerm> terms,
             final boolean mandatory)
+    {
+        this(idSuffix, label, terms, mandatory, null, null);
+    }
+
+    private VocabularyTermSelectionWidget(String idSuffix, String label,
+            List<VocabularyTerm> terms, boolean mandatory, Vocabulary vocabularyOrNull,
+            IViewContext<?> viewContextOrNull)
     {
         super(idSuffix, ModelDataPropertyNames.CODE, label, CHOOSE_MSG, EMPTY_MSG,
                 VALUE_NOT_IN_LIST_MSG, mandatory);
+        this.viewContextOrNull = viewContextOrNull;
+        this.vocabularyOrNull = vocabularyOrNull;
+
         FieldUtil.setMandatoryFlag(this, mandatory);
         setAllowBlank(mandatory == false);
+        setTerms(terms);
+    }
+
+    private void setTerms(List<VocabularyTerm> terms)
+    {
         final List<VocabularyTermModel> models = new ArrayList<VocabularyTermModel>();
         models.add(new VocabularyTermModel(GWTUtils.NONE_LIST_ITEM));
-        models.addAll(VocabularyTermModel.convert(terms));
+        models.addAll(convertItems(terms));
         updateStore(models);
         getPropertyEditor().setList(store.getModels());
     }
 
+    @Override
+    public void refreshStore()
+    {
+        if (viewContextOrNull != null)
+        {
+            refreshStore(viewContextOrNull);
+        }
+    }
+
+    @Override
+    protected List<VocabularyTermModel> convertItems(List<VocabularyTerm> result)
+    {
+        return VocabularyTermModel.convert(result);
+    }
+
+    @Override
+    protected void loadData(AbstractAsyncCallback<List<VocabularyTerm>> callback)
+    {
+        if (viewContextOrNull != null && vocabularyOrNull != null)
+        {
+            viewContextOrNull.getCommonService().listVocabularyTerms(vocabularyOrNull, callback);
+        }
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.VOCABULARY_TERM);
+    }
 }
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 15dce9c941d055e2d6384b0cead7796fb8119d21..b95c19434cefa7cdc722d5738f8edb3d49301373 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
@@ -211,7 +211,13 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod
     // !!!!!!!!!!!!!!!!!!!!!!!!!
     public void update(Set<DatabaseModificationKind> observedModifications)
     {
-        System.out.println("grid refresh requested: " + observedModifications);
+        System.out.println("generic grid refresh requested: " + observedModifications);
+        refreshGridSilently();
+    }
+
+    /** Refreshes the grid without showing the loading progress bar */
+    protected void refreshGridSilently()
+    {
         grid.setLoadMask(false);
         refresh();
         grid.setLoadMask(true);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialRegistrationPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialRegistrationPanel.java
deleted file mode 100644
index 0aff0510697c05b274af9ed308fb954fd0a32e2f..0000000000000000000000000000000000000000
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialRegistrationPanel.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-* Copyright 2008 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.ui.material;
-
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.MaterialTypeModel;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.EntityRegistrationPanel;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
-
-/**
- * The {@link EntityRegistrationPanel} extension for registering an material.
- * 
- * @author Izabela Adamczyk
- */
-public final class MaterialRegistrationPanel extends
-        EntityRegistrationPanel<MaterialTypeModel, MaterialTypeSelectionWidget>
-{
-
-    public static final String ID = EntityRegistrationPanel.createId(EntityKind.MATERIAL);
-
-    public MaterialRegistrationPanel(final CommonViewContext viewContext)
-    {
-        super(viewContext, EntityKind.MATERIAL, new MaterialTypeSelectionWidget(viewContext,
-                EntityRegistrationPanel.createId(EntityKind.MATERIAL)));
-    }
-
-}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialTypeSelectionWidget.java
index 48fb6e3ac9af929792d49c78c28747f885779aff..ad50c16ed5174c24b621a449adfa1055af9f2ac5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/material/MaterialTypeSelectionWidget.java
@@ -27,7 +27,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewConte
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.MaterialTypeModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of material types loaded from the server.
@@ -122,4 +124,9 @@ public final class MaterialTypeSelectionWidget extends
     {
         viewContext.getService().listMaterialTypes(callback);
     }
+    
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.MATERIAL_TYPE);
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/DataTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/DataTypeSelectionWidget.java
index a089b1f87ed69928a5394a874a7f386de8e424a7..e4459dbb61c2772c9af777965f305f4c569a9ad4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/DataTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/DataTypeSelectionWidget.java
@@ -30,6 +30,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Mode
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 
 /**
  * A {@link ComboBox} extension for selecting a {@link DataType}.
@@ -102,4 +103,9 @@ public final class DataTypeSelectionWidget extends DropDownList<DataTypeModel, D
     {
         viewContext.getService().listDataTypes(new ListDataTypesCallback(viewContext));
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.EMPTY_ARRAY;
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
index 477b7f569bd0a4164a477ca4dc79cb90a3287336..e496eab18e6e8ad50dbf496282b799e0d04cb321 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
@@ -16,322 +16,375 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type;
 
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.Events;
+import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
+import com.extjs.gxt.ui.client.Style.Scroll;
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.ButtonEvent;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.LayoutContainer;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.form.CheckBox;
+import com.extjs.gxt.ui.client.widget.form.Field;
+import com.extjs.gxt.ui.client.widget.form.FormPanel;
+import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
+import com.google.gwt.user.client.Element;
+
 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.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.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.CompositeDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm.InfoBoxResetListener;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment.ExperimentTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.PropertyFieldFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.MaterialTypeSelectionWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.SampleTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.InfoBox;
+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.PropertyType;
 
-import com.extjs.gxt.ui.client.Events;
-import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
-import com.extjs.gxt.ui.client.Style.Scroll;
-import com.extjs.gxt.ui.client.event.BaseEvent;
-import com.extjs.gxt.ui.client.event.ButtonEvent;
-import com.extjs.gxt.ui.client.event.Listener;
-import com.extjs.gxt.ui.client.event.SelectionListener;
-import com.extjs.gxt.ui.client.widget.LayoutContainer;
-import com.extjs.gxt.ui.client.widget.button.Button;
-import com.extjs.gxt.ui.client.widget.form.CheckBox;
-import com.extjs.gxt.ui.client.widget.form.ComboBox;
-import com.extjs.gxt.ui.client.widget.form.Field;
-import com.extjs.gxt.ui.client.widget.form.FormPanel;
-import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
-import com.google.gwt.user.client.Element;
-
 /**
  * The property type assignment panel.
  * 
  * @author Izabela Adamczyk
  */
-public final class PropertyTypeAssignmentForm extends LayoutContainer {
-	private static final String UNSUPPORTED_ENTITY_KIND = "Unsupported entity kind";
+public final class PropertyTypeAssignmentForm extends LayoutContainer implements
+        IDatabaseModificationObserver
+{
+    private static final String UNSUPPORTED_ENTITY_KIND = "Unsupported entity kind";
+
+    private static final int LABEL_WIDTH = 130;
+
+    private static final int FIELD_WIDTH = 400;
+
+    private static final String PREFIX = "property-type-assignment_";
+
+    public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
 
-	private static final int LABEL_WIDTH = 130;
+    public static final String PROPERTY_TYPE_ID_SUFFIX = "property_type";
 
-	private static final int FIELD_WIDTH = 400;
+    public static final String SAMPLE_TYPE_ID_SUFFIX = ID_PREFIX + "sample_type";
 
-	private static final String PREFIX = "property-type-assignment_";
+    public static final String EXPERIMENT_TYPE_ID_SUFFIX = ID_PREFIX + "experiment_type";
 
-	public static final String ID_PREFIX = GenericConstants.ID_PREFIX + PREFIX;
+    public static final String MATERIAL_TYPE_ID_SUFFIX = ID_PREFIX + "material_type";
 
-	public static final String PROPERTY_TYPE_ID_SUFFIX = "property_type";
+    public static final String DATA_SET_TYPE_ID_SUFFIX = ID_PREFIX + "data_set_type";
 
-	public static final String SAMPLE_TYPE_ID_SUFFIX = ID_PREFIX
-			+ "sample_type";
+    public static final String MANDATORY_CHECKBOX_ID_SUFFIX = "mandatory_checkbox";
 
-	public static final String EXPERIMENT_TYPE_ID_SUFFIX = ID_PREFIX
-			+ "experiment_type";
+    public static final String SAVE_BUTTON_ID_SUFFIX = "save-button";
 
-	public static final String MATERIAL_TYPE_ID_SUFFIX = ID_PREFIX
-			+ "material_type";
-
-	public static final String DATA_SET_TYPE_ID_SUFFIX = ID_PREFIX
-			+ "data_set_type";
-
-	public static final String MANDATORY_CHECKBOX_ID_SUFFIX = "mandatory_checkbox";
-
-	public static final String SAVE_BUTTON_ID_SUFFIX = "save-button";
-
-	protected static final String DEFAULT_VALUE_ID_PART = "default_value";
-
-	private final IViewContext<ICommonClientServiceAsync> viewContext;
-
-	private SampleTypeSelectionWidget sampleTypeSelectionWidget;
-
-	private ExperimentTypeSelectionWidget experimentTypeSelectionWidget;
-
-	private MaterialTypeSelectionWidget materialTypeSelectionWidget;
-
-	private DataSetTypeSelectionWidget dataSetTypeSelectionWidget;
-
-	private PropertyTypeSelectionWidget propertyTypeSelectionWidget;
-
-	private Field<?> defaultValueField;
-
-	private CheckBox mandatoryCheckbox;
-
-	private final InfoBox infoBox;
-
-	private final FormPanel formPanel;
-
-	private final EntityKind entityKind;
-
-	public PropertyTypeAssignmentForm(
-			final IViewContext<ICommonClientServiceAsync> viewContext,
-			EntityKind entityKind) {
-		this.entityKind = entityKind;
-		setLayout(new FlowLayout(5));
-		setId(createId(entityKind));
-		this.viewContext = viewContext;
-		setScrollMode(Scroll.AUTO);
-		add(infoBox = createInfoBox());
-		add(formPanel = createFormPanel());
-	}
-
-	public static final String createId(EntityKind entityKind) {
-		return ID_PREFIX + entityKind.name();
-	}
-
-	private String createChildId(String childSuffix) {
-		return getId() + childSuffix;
-	}
-
-	private final static InfoBox createInfoBox() {
-		final InfoBox infoBox = new InfoBox();
-		return infoBox;
-	}
-
-	private PropertyTypeSelectionWidget getPropertyTypeWidget() {
-		if (propertyTypeSelectionWidget == null) {
-			propertyTypeSelectionWidget = new PropertyTypeSelectionWidget(
-					viewContext, createChildId(PROPERTY_TYPE_ID_SUFFIX));
-			propertyTypeSelectionWidget.addListener(Events.Focus,
-					new InfoBoxResetListener(infoBox));
-			FieldUtil.markAsMandatory(propertyTypeSelectionWidget);
-			propertyTypeSelectionWidget.addListener(Events.SelectionChange,
-					new Listener<BaseEvent>() {
-						public void handleEvent(BaseEvent be) {
-							updateDefaultField();
-						}
-					});
-		}
-		return propertyTypeSelectionWidget;
-	}
-
-	private ComboBox<?> getTypeSelectionWidget() {
-		switch (entityKind) {
-		case EXPERIMENT:
-			if (experimentTypeSelectionWidget == null) {
-				experimentTypeSelectionWidget = new ExperimentTypeSelectionWidget(
-						viewContext, EXPERIMENT_TYPE_ID_SUFFIX);
-				experimentTypeSelectionWidget.addListener(Events.Focus,
-						new InfoBoxResetListener(infoBox));
-				FieldUtil.markAsMandatory(experimentTypeSelectionWidget);
-			}
-			return experimentTypeSelectionWidget;
-		case SAMPLE:
-			if (sampleTypeSelectionWidget == null) {
-				sampleTypeSelectionWidget = new SampleTypeSelectionWidget(
-						viewContext, SAMPLE_TYPE_ID_SUFFIX, false);
-				sampleTypeSelectionWidget.addListener(Events.Focus,
-						new InfoBoxResetListener(infoBox));
-				FieldUtil.markAsMandatory(sampleTypeSelectionWidget);
-			}
-			return sampleTypeSelectionWidget;
-		case MATERIAL:
-			if (materialTypeSelectionWidget == null) {
-				materialTypeSelectionWidget = new MaterialTypeSelectionWidget(
-						viewContext, MATERIAL_TYPE_ID_SUFFIX);
-				materialTypeSelectionWidget.addListener(Events.Focus,
-						new InfoBoxResetListener(infoBox));
-				FieldUtil.markAsMandatory(materialTypeSelectionWidget);
-			}
-			return materialTypeSelectionWidget;
-		case DATA_SET:
-			if (dataSetTypeSelectionWidget == null) {
-				dataSetTypeSelectionWidget = new DataSetTypeSelectionWidget(
-						viewContext, DATA_SET_TYPE_ID_SUFFIX);
-				dataSetTypeSelectionWidget.addListener(Events.Focus,
-						new InfoBoxResetListener(infoBox));
-				FieldUtil.markAsMandatory(dataSetTypeSelectionWidget);
-			}
-			return dataSetTypeSelectionWidget;
-		}
-		throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
-	}
-
-	private CheckBox getMandatoryCheckbox() {
-		if (mandatoryCheckbox == null) {
-			mandatoryCheckbox = new CheckBox();
-			mandatoryCheckbox
-					.setId(createChildId(MANDATORY_CHECKBOX_ID_SUFFIX));
-			mandatoryCheckbox.setFieldLabel(viewContext
-					.getMessage(Dict.MANDATORY));
-			mandatoryCheckbox.setValue(false);
-			mandatoryCheckbox.addListener(Events.Change,
-					new InfoBoxResetListener(infoBox));
-		}
-		return mandatoryCheckbox;
-	}
-
-	private final FormPanel createFormPanel() {
-		final FormPanel panel = new FormPanel();
-		panel.setHeaderVisible(false);
-		panel.setBodyBorder(false);
-		panel.setWidth(LABEL_WIDTH + FIELD_WIDTH + 40);
-		panel.setLabelWidth(LABEL_WIDTH);
-		panel.setFieldWidth(FIELD_WIDTH);
-		panel.setButtonAlign(HorizontalAlignment.RIGHT);
-		final Button saveButton = new Button(viewContext
-				.getMessage(Dict.BUTTON_SAVE));
-		saveButton.setStyleAttribute("marginRight", "20px");
-		saveButton.setId(createChildId(SAVE_BUTTON_ID_SUFFIX));
-		saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
-			@Override
-			public final void componentSelected(final ButtonEvent ce) {
-				submitForm();
-			}
-		});
-		final Button resetButton = new Button(viewContext
-				.getMessage(Dict.BUTTON_RESET));
-		resetButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
-			@Override
-			public final void componentSelected(final ButtonEvent ce) {
-				resetForm();
-			}
-		});
-		panel.addButton(resetButton);
-		panel.addButton(saveButton);
-		return panel;
-	}
-
-	private String getDefaultValue() {
-		if (defaultValueField != null) {
-			return PropertyFieldFactory.valueToString(defaultValueField
-					.getValue());
-		}
-		return null;
-	}
-
-	private String getSelectedEntityCode() {
-		switch (entityKind) {
-		case EXPERIMENT:
-			return experimentTypeSelectionWidget.tryGetSelectedExperimentType()
-					.getCode();
-		case SAMPLE:
-			return sampleTypeSelectionWidget.tryGetSelectedSampleType()
-					.getCode();
-		case MATERIAL:
-			return materialTypeSelectionWidget.tryGetSelectedMaterialType()
-					.getCode();
-		case DATA_SET:
-			return dataSetTypeSelectionWidget.tryGetSelectedDataSetType()
-					.getCode();
-		}
-		throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
-	}
-
-	private final void addFormFields() {
-		formPanel.add(getPropertyTypeWidget());
-		formPanel.add(getTypeSelectionWidget());
-		formPanel.add(getMandatoryCheckbox());
-		updateDefaultField();
-	}
-
-	@Override
-	protected final void onRender(final Element target, final int index) {
-		super.onRender(target, index);
-		addFormFields();
-	}
-
-	public final class AssignPropertyTypeCallback extends
-			AbstractAsyncCallback<String> {
-		AssignPropertyTypeCallback(final IViewContext<?> viewContext) {
-			super(viewContext, new InfoBoxCallbackListener<String>(infoBox));
-		}
-
-		@Override
-		protected final void process(final String result) {
-			infoBox.displayInfo(result);
-			resetForm();
-		}
-	}
-
-	private void updateDefaultField() {
-		hideDefaultField();
-		final PropertyType propertyType = propertyTypeSelectionWidget
-				.tryGetSelectedPropertyType();
-		if (propertyType != null) {
-			String fieldId = createChildId(DEFAULT_VALUE_ID_PART
-					+ propertyType.isInternalNamespace()
-					+ propertyType.getSimpleCode());
-			Field<?> field = PropertyFieldFactory.createField(propertyType,
-					false, viewContext.getMessage(Dict.DEFAULT_VALUE), fieldId,
-					null, viewContext);
-			field
-					.setToolTip(viewContext
-							.getMessage(Dict.DEFAULT_VALUE_TOOLTIP));
-			defaultValueField = field;
-			defaultValueField.show();
-			formPanel.add(defaultValueField);
-		}
-		layout();
-	}
-
-	private void hideDefaultField() {
-		if (defaultValueField != null) {
-			defaultValueField.hide();
-			formPanel.remove(defaultValueField);
-			defaultValueField = null;
-		}
-	}
-
-	private final void submitForm() {
-		if (formPanel.isValid()) {
-			viewContext.getService().assignPropertyType(
-					entityKind,
-					propertyTypeSelectionWidget
-							.tryGetSelectedPropertyTypeCode(),
-					getSelectedEntityCode(), getMandatoryCheckbox().getValue(),
-					getDefaultValue(),
-					new AssignPropertyTypeCallback(viewContext));
-		}
-	}
-
-	private void resetForm() {
-		formPanel.reset();
-		updateDefaultField();
-	}
+    protected static final String DEFAULT_VALUE_ID_PART = "default_value";
+
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private SampleTypeSelectionWidget sampleTypeSelectionWidget;
+
+    private ExperimentTypeSelectionWidget experimentTypeSelectionWidget;
+
+    private MaterialTypeSelectionWidget materialTypeSelectionWidget;
+
+    private DataSetTypeSelectionWidget dataSetTypeSelectionWidget;
+
+    private PropertyTypeSelectionWidget propertyTypeSelectionWidget;
+
+    private DatabaseModificationAwareField<?> defaultValueField;
+
+    private CheckBox mandatoryCheckbox;
+
+    private final InfoBox infoBox;
+
+    private final FormPanel formPanel;
+
+    private final CompositeDatabaseModificationObserver modificationManager;
+
+    private final EntityKind entityKind;
+
+    public static DatabaseModificationAwareComponent create(
+            final IViewContext<ICommonClientServiceAsync> viewContext, EntityKind entityKind)
+    {
+        PropertyTypeAssignmentForm form = new PropertyTypeAssignmentForm(viewContext, entityKind);
+        return new DatabaseModificationAwareComponent(form, form.modificationManager);
+    }
+
+    private PropertyTypeAssignmentForm(final IViewContext<ICommonClientServiceAsync> viewContext,
+            EntityKind entityKind)
+    {
+        this.entityKind = entityKind;
+        this.modificationManager = new CompositeDatabaseModificationObserver();
+        setLayout(new FlowLayout(5));
+        setId(createId(entityKind));
+        this.viewContext = viewContext;
+        setScrollMode(Scroll.AUTO);
+        add(infoBox = createInfoBox());
+        add(formPanel = createFormPanel());
+    }
+
+    public static final String createId(EntityKind entityKind)
+    {
+        return ID_PREFIX + entityKind.name();
+    }
+
+    private String createChildId(String childSuffix)
+    {
+        return getId() + childSuffix;
+    }
+
+    private final static InfoBox createInfoBox()
+    {
+        final InfoBox infoBox = new InfoBox();
+        return infoBox;
+    }
+
+    private PropertyTypeSelectionWidget getPropertyTypeWidget()
+    {
+        if (propertyTypeSelectionWidget == null)
+        {
+            propertyTypeSelectionWidget =
+                    new PropertyTypeSelectionWidget(viewContext,
+                            createChildId(PROPERTY_TYPE_ID_SUFFIX));
+            propertyTypeSelectionWidget
+                    .addListener(Events.Focus, new InfoBoxResetListener(infoBox));
+            FieldUtil.markAsMandatory(propertyTypeSelectionWidget);
+            propertyTypeSelectionWidget.addListener(Events.SelectionChange,
+                    new Listener<BaseEvent>()
+                        {
+                            public void handleEvent(BaseEvent be)
+                            {
+                                updateDefaultField();
+                            }
+                        });
+        }
+        return propertyTypeSelectionWidget;
+    }
+
+    private DropDownList<?, ?> getTypeSelectionWidget()
+    {
+        switch (entityKind)
+        {
+            case EXPERIMENT:
+                if (experimentTypeSelectionWidget == null)
+                {
+                    experimentTypeSelectionWidget =
+                            new ExperimentTypeSelectionWidget(viewContext,
+                                    EXPERIMENT_TYPE_ID_SUFFIX);
+                    experimentTypeSelectionWidget.addListener(Events.Focus,
+                            new InfoBoxResetListener(infoBox));
+                    FieldUtil.markAsMandatory(experimentTypeSelectionWidget);
+                }
+                return experimentTypeSelectionWidget;
+            case SAMPLE:
+                if (sampleTypeSelectionWidget == null)
+                {
+                    sampleTypeSelectionWidget =
+                            new SampleTypeSelectionWidget(viewContext, SAMPLE_TYPE_ID_SUFFIX, false);
+                    sampleTypeSelectionWidget.addListener(Events.Focus, new InfoBoxResetListener(
+                            infoBox));
+                    FieldUtil.markAsMandatory(sampleTypeSelectionWidget);
+                }
+                return sampleTypeSelectionWidget;
+            case MATERIAL:
+                if (materialTypeSelectionWidget == null)
+                {
+                    materialTypeSelectionWidget =
+                            new MaterialTypeSelectionWidget(viewContext, MATERIAL_TYPE_ID_SUFFIX);
+                    materialTypeSelectionWidget.addListener(Events.Focus, new InfoBoxResetListener(
+                            infoBox));
+                    FieldUtil.markAsMandatory(materialTypeSelectionWidget);
+                }
+                return materialTypeSelectionWidget;
+            case DATA_SET:
+                if (dataSetTypeSelectionWidget == null)
+                {
+                    dataSetTypeSelectionWidget =
+                            new DataSetTypeSelectionWidget(viewContext, DATA_SET_TYPE_ID_SUFFIX);
+                    dataSetTypeSelectionWidget.addListener(Events.Focus, new InfoBoxResetListener(
+                            infoBox));
+                    FieldUtil.markAsMandatory(dataSetTypeSelectionWidget);
+                }
+                return dataSetTypeSelectionWidget;
+        }
+        throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
+    }
+
+    private CheckBox getMandatoryCheckbox()
+    {
+        if (mandatoryCheckbox == null)
+        {
+            mandatoryCheckbox = new CheckBox();
+            mandatoryCheckbox.setId(createChildId(MANDATORY_CHECKBOX_ID_SUFFIX));
+            mandatoryCheckbox.setFieldLabel(viewContext.getMessage(Dict.MANDATORY));
+            mandatoryCheckbox.setValue(false);
+            mandatoryCheckbox.addListener(Events.Change, new InfoBoxResetListener(infoBox));
+        }
+        return mandatoryCheckbox;
+    }
+
+    private final FormPanel createFormPanel()
+    {
+        final FormPanel panel = new FormPanel();
+        panel.setHeaderVisible(false);
+        panel.setBodyBorder(false);
+        panel.setWidth(LABEL_WIDTH + FIELD_WIDTH + 40);
+        panel.setLabelWidth(LABEL_WIDTH);
+        panel.setFieldWidth(FIELD_WIDTH);
+        panel.setButtonAlign(HorizontalAlignment.RIGHT);
+        final Button saveButton = new Button(viewContext.getMessage(Dict.BUTTON_SAVE));
+        saveButton.setStyleAttribute("marginRight", "20px");
+        saveButton.setId(createChildId(SAVE_BUTTON_ID_SUFFIX));
+        saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
+            {
+                @Override
+                public final void componentSelected(final ButtonEvent ce)
+                {
+                    submitForm();
+                }
+            });
+        final Button resetButton = new Button(viewContext.getMessage(Dict.BUTTON_RESET));
+        resetButton.addSelectionListener(new SelectionListener<ButtonEvent>()
+            {
+                @Override
+                public final void componentSelected(final ButtonEvent ce)
+                {
+                    resetForm();
+                }
+            });
+        panel.addButton(resetButton);
+        panel.addButton(saveButton);
+        return panel;
+    }
+
+    private String getDefaultValue()
+    {
+        if (defaultValueField != null)
+        {
+            return PropertyFieldFactory.valueToString(defaultValueField.get().getValue());
+        }
+        return null;
+    }
+
+    private String getSelectedEntityCode()
+    {
+        switch (entityKind)
+        {
+            case EXPERIMENT:
+                return experimentTypeSelectionWidget.tryGetSelectedExperimentType().getCode();
+            case SAMPLE:
+                return sampleTypeSelectionWidget.tryGetSelectedSampleType().getCode();
+            case MATERIAL:
+                return materialTypeSelectionWidget.tryGetSelectedMaterialType().getCode();
+            case DATA_SET:
+                return dataSetTypeSelectionWidget.tryGetSelectedDataSetType().getCode();
+        }
+        throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
+    }
+
+    private final void addFormFields()
+    {
+        PropertyTypeSelectionWidget propertyTypeWidget = getPropertyTypeWidget();
+        DropDownList<?, ?> typeSelectionWidget = getTypeSelectionWidget();
+        formPanel.add(propertyTypeWidget);
+        formPanel.add(typeSelectionWidget);
+        formPanel.add(getMandatoryCheckbox());
+        updateDefaultField();
+
+        // TODO 2009-03-30, Tomasz Pylak: add auto-refreshing of the initial value field
+        modificationManager.addObserver(propertyTypeWidget);
+        modificationManager.addObserver(typeSelectionWidget);
+    }
+
+    @Override
+    protected final void onRender(final Element target, final int index)
+    {
+        super.onRender(target, index);
+        addFormFields();
+    }
+
+    public final class AssignPropertyTypeCallback extends AbstractAsyncCallback<String>
+    {
+        AssignPropertyTypeCallback(final IViewContext<?> viewContext)
+        {
+            super(viewContext, new InfoBoxCallbackListener<String>(infoBox));
+        }
+
+        @Override
+        protected final void process(final String result)
+        {
+            infoBox.displayInfo(result);
+            resetForm();
+        }
+    }
+
+    private void updateDefaultField()
+    {
+        hideDefaultField();
+        final PropertyType propertyType = propertyTypeSelectionWidget.tryGetSelectedPropertyType();
+        if (propertyType != null)
+        {
+            String fieldId =
+                    createChildId(DEFAULT_VALUE_ID_PART + propertyType.isInternalNamespace()
+                            + propertyType.getSimpleCode());
+            DatabaseModificationAwareField<?> fieldHolder =
+                    PropertyFieldFactory.createField(propertyType, false, viewContext
+                            .getMessage(Dict.DEFAULT_VALUE), fieldId, null, viewContext);
+            fieldHolder.get().setToolTip(viewContext.getMessage(Dict.DEFAULT_VALUE_TOOLTIP));
+            defaultValueField = fieldHolder;
+            defaultValueField.get().show();
+            formPanel.add(defaultValueField.get());
+        }
+        layout();
+    }
+
+    private void hideDefaultField()
+    {
+        if (defaultValueField != null)
+        {
+            Field<?> field = defaultValueField.get();
+            field.hide();
+            formPanel.remove(field);
+            defaultValueField = null;
+        }
+    }
+
+    private final void submitForm()
+    {
+        if (formPanel.isValid())
+        {
+            viewContext.getService().assignPropertyType(entityKind,
+                    propertyTypeSelectionWidget.tryGetSelectedPropertyTypeCode(),
+                    getSelectedEntityCode(), getMandatoryCheckbox().getValue(), getDefaultValue(),
+                    new AssignPropertyTypeCallback(viewContext));
+        }
+    }
+
+    private void resetForm()
+    {
+        formPanel.reset();
+        updateDefaultField();
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return modificationManager.getRelevantModifications();
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        modificationManager.update(observedModifications);
+    }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
index 66baaf0ed4dce817238b5100d8c76c03948b4e9c..4da48e6c96bfd630b3e0911bad85172c91a2d9fd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeSelectionWidget.java
@@ -31,7 +31,9 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.Mode
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.DropDownList;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 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.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of property type codes loaded from the server.
@@ -130,4 +132,9 @@ public final class PropertyTypeSelectionWidget extends
         viewContext.getService().listPropertyTypes(config,
                 new ListPropertyTypesCallback(viewContext));
     }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.PROPERTY_TYPE);
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/DropDownList.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/DropDownList.java
index bcfc961ac424c33d8702daaf3747ed60ea41a603..b5e873fd58ac11b546641ba7a5c1376521e10a36 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/DropDownList.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/DropDownList.java
@@ -16,13 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample;
 
-import java.util.List;
-
 import com.extjs.gxt.ui.client.data.ModelData;
 import com.extjs.gxt.ui.client.widget.form.ComboBox;
 import com.google.gwt.user.client.Element;
 
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 
@@ -46,31 +43,17 @@ public abstract class DropDownList<M extends ModelData, E> extends SimpleDropDow
         this.viewContext = viewContext;
     }
 
-    abstract protected void loadData(AbstractAsyncCallback<List<E>> callback);
-
-    abstract protected List<M> convertItems(final List<E> result);
-
     @Override
     protected void onRender(final Element parent, final int pos)
     {
         super.onRender(parent, pos);
-        loadData(new ListItemsCallback(viewContext));
+        refreshStore();
     }
 
-    public class ListItemsCallback extends AbstractAsyncCallback<List<E>>
+    @Override
+    public void refreshStore()
     {
-
-        protected ListItemsCallback(final IViewContext<?> viewContext)
-        {
-            super(viewContext);
-        }
-
-        @Override
-        public void process(final List<E> result)
-        {
-            List<M> convertedItems = convertItems(result);
-            updateStore(convertedItems);
-        }
+        refreshStore(viewContext);
     }
 
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleRegistrationPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleRegistrationPanel.java
index f74227588ea8e71112cfc083880c2efc5474a74f..0ce250feb4559d61674f3fc51f61a4e42b5c323f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleRegistrationPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleRegistrationPanel.java
@@ -1,22 +1,23 @@
 /*
-* Copyright 2008 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.
-*/
+ * Copyright 2008 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.ui.sample;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.CommonViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.SampleTypeModel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.EntityRegistrationPanel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
@@ -32,7 +33,14 @@ public final class SampleRegistrationPanel extends
 
     public static final String ID = EntityRegistrationPanel.createId(EntityKind.SAMPLE);
 
-    public SampleRegistrationPanel(final CommonViewContext viewContext)
+    public static final DatabaseModificationAwareComponent create(
+            final CommonViewContext viewContext)
+    {
+        SampleRegistrationPanel panel = new SampleRegistrationPanel(viewContext);
+        return new DatabaseModificationAwareComponent(panel, panel);
+    }
+
+    private SampleRegistrationPanel(final CommonViewContext viewContext)
     {
         super(viewContext, EntityKind.SAMPLE, new SampleTypeSelectionWidget(viewContext,
                 EntityRegistrationPanel.createId(EntityKind.SAMPLE), false));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
index 74725886f973d06f2fce39ca05f5bfeb856670df..2b8d3fe0624a5ccfcacff2205c2cc0477526956f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
@@ -25,7 +25,9 @@ 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.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.SampleTypeModel;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
  * {@link ComboBox} containing list of sample types loaded from the server.
@@ -69,6 +71,10 @@ public final class SampleTypeSelectionWidget extends DropDownList<SampleTypeMode
     protected void loadData(AbstractAsyncCallback<List<SampleType>> callback)
     {
         viewContext.getCommonService().listSampleTypes(callback);
+    }
 
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return DatabaseModificationKind.any(ObjectKind.SAMPLE_TYPE);
     }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SimpleDropDownList.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SimpleDropDownList.java
index c329b8f1cad4244b0537a01a533787a58e059a90..76f11f4f2fef8258948eb0e82f94ca69266f0566 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SimpleDropDownList.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SimpleDropDownList.java
@@ -16,20 +16,44 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 import com.extjs.gxt.ui.client.data.ModelData;
 import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.store.Store;
 import com.extjs.gxt.ui.client.widget.form.ComboBox;
 
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
 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.framework.DatabaseModificationAwareField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 
 /**
  * @author Izabela Adamczyk
  */
-public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
+abstract public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M> implements
+        IDatabaseModificationObserver
 {
+
+    /**
+     * Refreshes the whole store of the combobox. If the previously chosen value is no longer
+     * present in the store, it will be changed to empty. Otherwise the previous selection will be
+     * preserved.
+     */
+    abstract public void refreshStore();
+
+    abstract protected void loadData(AbstractAsyncCallback<List<E>> callback);
+
+    abstract protected List<M> convertItems(final List<E> result);
+
+    // ----------
+
     private static final int DEFAULT_WIDTH = 150;
 
     private static final String PREFIX = "select_";
@@ -61,7 +85,38 @@ public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
         setStore(new ListStore<M>());
     }
 
-    public void updateStore(final List<M> models)
+    public DatabaseModificationAwareField<M> asDatabaseModificationAware()
+    {
+        return new DatabaseModificationAwareField<M>(this, this);
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        refreshStore();
+    }
+
+    protected void refreshStore(final IViewContext<?> viewContext)
+    {
+        loadData(new ListItemsCallback(viewContext));
+    }
+
+    public class ListItemsCallback extends AbstractAsyncCallback<List<E>>
+    {
+
+        protected ListItemsCallback(final IViewContext<?> viewContext)
+        {
+            super(viewContext);
+        }
+
+        @Override
+        public void process(final List<E> result)
+        {
+            List<M> convertedItems = convertItems(result);
+            updateStore(convertedItems);
+        }
+    }
+
+    protected void updateStore(final List<M> models)
     {
         final ListStore<M> termsStore = getStore();
         termsStore.removeAll();
@@ -70,6 +125,11 @@ public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
         {
             setEmptyText(chooseMsg);
             setReadOnly(false);
+            if (getValue() != null && getSelection().size() == 0)
+            {
+                validate(); // maybe the value became a valid selection
+            }
+            restoreSelection(getSelection());
         } else
         {
             setEmptyText(emptyMsg);
@@ -78,6 +138,74 @@ public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
         applyEmptyText();
     }
 
+    private void restoreSelection(List<M> previousSelection)
+    {
+        List<M> newSelection = cleanSelection(previousSelection, getStore());
+        if (previousSelection.size() != newSelection.size())
+        {
+            setSelection(newSelection);
+        }
+    }
+
+    // removes the no longer existing items from the selection
+    private static <M extends ModelData> List<M> cleanSelection(List<M> previousSelection,
+            Store<M> newStore)
+    {
+        List<M> newSelection = new ArrayList<M>();
+        for (M prevItem : previousSelection)
+        {
+            if (containsModel(newStore, prevItem))
+            {
+                newSelection.add(prevItem);
+            }
+        }
+        return newSelection;
+    }
+
+    private static <M extends ModelData> boolean containsModel(Store<M> store, M item)
+    {
+        for (M elem : store.getModels())
+        {
+            if (equalsModel(elem, item))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static <M extends ModelData> boolean equalsModel(M model1, M model2)
+    {
+        Collection<String> props1 = model1.getPropertyNames();
+        Collection<String> props2 = model1.getPropertyNames();
+        if (props1.equals(props2) == false)
+        {
+            return false;
+        }
+        for (String propName : props1)
+        {
+            Object val1 = model1.get(propName);
+            Object val2 = model2.get(propName);
+            if (val1 == null)
+            {
+                if (val2 != null)
+                {
+                    return false;
+                } else
+                {
+                    continue;
+                }
+            } else
+            {
+                if (val1.equals(val2) == false)
+                {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     @Override
     public String getRawValue()
     {
@@ -149,8 +277,7 @@ public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
     {
         clearInvalid();
         markInvalidIfNotFromList();
-        return super.isValid() && valueNotInTheList() == false
-                ;
+        return super.isValid() && valueNotInTheList() == false;
     }
 
     @Override
@@ -158,8 +285,7 @@ public class SimpleDropDownList<M extends ModelData, E> extends ComboBox<M>
     {
         clearInvalid();
         markInvalidIfNotFromList();
-        return super.validate() && valueNotInTheList() == false
-                ;
+        return super.validate() && valueNotInTheList() == false;
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/EntityRegistrationPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/EntityRegistrationPanel.java
index dcebf1b34f2a6f08a03b8b7cbaa436836f2dba52..2efee3840d4fd54eea0290b8ce9b181a7b5b7e7b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/EntityRegistrationPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/EntityRegistrationPanel.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import com.extjs.gxt.ui.client.Style.Scroll;
 import com.extjs.gxt.ui.client.data.ModelData;
@@ -25,18 +26,21 @@ import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
 import com.extjs.gxt.ui.client.event.SelectionChangedListener;
 import com.extjs.gxt.ui.client.widget.ContentPanel;
 import com.extjs.gxt.ui.client.widget.LayoutContainer;
-import com.extjs.gxt.ui.client.widget.form.ComboBox;
 import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.LabelToolItem;
 import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
-import com.google.gwt.user.client.ui.Widget;
 
 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.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.CompositeDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.ModelDataPropertyNames;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.plugin.IClientPlugin;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.SimpleDropDownList;
 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;
@@ -47,11 +51,19 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
  * 
  * @author Izabela Adamczyk
  */
-abstract public class EntityRegistrationPanel<T extends ModelData, S extends ComboBox<T>> extends
-        ContentPanel
+abstract public class EntityRegistrationPanel<T extends ModelData, S extends SimpleDropDownList<T, ?>>
+        extends ContentPanel implements IDatabaseModificationObserver
 {
     private final S entityTypeSelection;
 
+    private final CommonViewContext viewContext;
+
+    private final EntityKind entityKind;
+
+    private DatabaseModificationAwareWidget registrationWidget;
+
+    private PreviousSelection previousSelection = new PreviousSelection();
+
     protected static String createId(EntityKind entityKind)
     {
         return GenericConstants.ID_PREFIX + entityKind.name().toLowerCase() + "-registration";
@@ -61,6 +73,9 @@ abstract public class EntityRegistrationPanel<T extends ModelData, S extends Com
             S entityTypeSelection)
     {
         this.entityTypeSelection = entityTypeSelection;
+        this.viewContext = viewContext;
+        this.entityKind = entityKind;
+
         setHeaderVisible(false);
         setId(createId(entityKind));
         setScrollMode(Scroll.AUTO);
@@ -69,90 +84,103 @@ abstract public class EntityRegistrationPanel<T extends ModelData, S extends Com
                 + GenericConstants.LABEL_SEPARATOR));
         toolBar.add(new AdapterToolItem(entityTypeSelection));
         setTopComponent(toolBar);
-        entityTypeSelection.addSelectionChangedListener(new EntityTypeSelectionChangeListener(
-                viewContext, entityKind));
+        entityTypeSelection.addSelectionChangedListener(createSelectionChangedListener());
     }
 
-    private class EntityTypeSelectionChangeListener extends SelectionChangedListener<T>
+    private SelectionChangedListener<T> createSelectionChangedListener()
     {
+        return new SelectionChangedListener<T>()
+            {
+                @Override
+                public void selectionChanged(final SelectionChangedEvent<T> se)
+                {
+                    final T entityTypeModel = se.getSelectedItem();
+                    if (entityTypeModel != null)
+                    {
+                        onSelectionChanged(entityTypeModel);
+                    }
+                }
+            };
+    }
 
-        private Widget registrationWidget;
+    private void onSelectionChanged(final T entityTypeModel)
+    {
+        final EntityType entityType = entityTypeModel.get(ModelDataPropertyNames.OBJECT);
+        if (registrationWidget == null)
 
-        private final CommonViewContext viewContext;
+        {
+            showRegistrationForm(entityType);
+            previousSelection.update(entityTypeModel);
+        } else
+        {
+            new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE), viewContext
+                    .getMessage(Dict.CONFIRM_CLOSE_MSG))
+                {
+                    @Override
+                    protected void onYes()
+                    {
+                        showRegistrationForm(entityType);
+                        previousSelection.update(entityTypeModel);
+                    }
+
+                    @Override
+                    protected void onNo()
+                    {
+                        List<T> selection = new ArrayList<T>();
+                        selection.add(previousSelection.getValue());
+                        entityTypeSelection.disableEvents(true);
+                        entityTypeSelection.setSelection(selection);
+                        entityTypeSelection.disableEvents(false);
+                    }
+                }.show();
+        }
+    }
 
-        private PreviousSelection previousSelection = new PreviousSelection();
+    private void showRegistrationForm(final EntityType entityType)
+    {
+        removeAll();
+        final IClientPlugin<EntityType, EntityTypePropertyType<EntityType>, EntityProperty<EntityType, EntityTypePropertyType<EntityType>>, IIdentifierHolder, ?> clientPlugin =
+                viewContext.getClientPluginFactoryProvider().getClientPluginFactory(entityKind,
+                        entityType).createClientPlugin(entityKind);
+        registrationWidget = clientPlugin.createRegistrationForEntityType(entityType);
+        add(registrationWidget.get());
+        layout();
+    }
 
-        private final EntityKind entityKind;
+    private class PreviousSelection
+    {
+        T value;
 
-        public EntityTypeSelectionChangeListener(CommonViewContext viewContext,
-                EntityKind entityKind)
+        void update(T newValue)
         {
-            this.viewContext = viewContext;
-            this.entityKind = entityKind;
+            this.value = newValue;
         }
 
-        @Override
-        public void selectionChanged(final SelectionChangedEvent<T> se)
+        T getValue()
         {
-            final T entityTypeModel = se.getSelectedItem();
-            if (entityTypeModel != null)
-            {
-                final EntityType entityType = entityTypeModel.get(ModelDataPropertyNames.OBJECT);
-                if (registrationWidget == null)
-
-                {
-                    showRegistrationForm(entityType);
-                    previousSelection.update(entityTypeModel);
-                } else
-                {
-                    new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE), viewContext
-                            .getMessage(Dict.CONFIRM_CLOSE_MSG))
-                        {
-                            @Override
-                            protected void onYes()
-                            {
-                                showRegistrationForm(entityType);
-                                previousSelection.update(entityTypeModel);
-                            }
-
-                            @Override
-                            protected void onNo()
-                            {
-                                List<T> selection = new ArrayList<T>();
-                                selection.add(previousSelection.getValue());
-                                entityTypeSelection.disableEvents(true);
-                                entityTypeSelection.setSelection(selection);
-                                entityTypeSelection.disableEvents(false);
-                            }
-                        }.show();
-                }
-            }
+            return value;
         }
+    }
 
-        private void showRegistrationForm(final EntityType entityType)
+    private IDatabaseModificationObserver createCompositeDatabaseModificationObserver()
+    {
+        CompositeDatabaseModificationObserver observer =
+                new CompositeDatabaseModificationObserver();
+        if (registrationWidget != null)
         {
-            removeAll();
-            final IClientPlugin<EntityType, EntityTypePropertyType<EntityType>, EntityProperty<EntityType, EntityTypePropertyType<EntityType>>, IIdentifierHolder, ?> clientPlugin =
-                    viewContext.getClientPluginFactoryProvider().getClientPluginFactory(entityKind,
-                            entityType).createClientPlugin(entityKind);
-            registrationWidget = clientPlugin.createRegistrationForEntityType(entityType);
-            add(registrationWidget);
-            layout();
+            observer.addObserver(registrationWidget);
         }
+        observer.addObserver(entityTypeSelection);
+        return observer;
+    }
 
-        private class PreviousSelection
-        {
-            T value;
-
-            void update(T newValue)
-            {
-                this.value = newValue;
-            }
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return createCompositeDatabaseModificationObserver().getRelevantModifications();
+    }
 
-            T getValue()
-            {
-                return value;
-            }
-        }
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        createCompositeDatabaseModificationObserver().update(observedModifications);
     }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/util/SetUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/util/SetUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..8623f3bf994aa6d5d3af71b88d43a03a21c07392
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/util/SetUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Utility methods for sets and collections.
+ *
+ * @author Tomasz Pylak
+ */
+public class SetUtils
+{
+    /** Adds specified items to the specified collection. */
+    public static <T> void addAll(Collection<T> collection, T[] items)
+    {
+        for (T newElem : items)
+        {
+            collection.add(newElem);
+        }
+    }
+
+    /** @return true if the specified set contains any item from the specified items */
+    public static <T> boolean containsAny(Set<T> set, Set<T> items)
+    {
+        Set<T> setCopy = new HashSet<T>(set);
+        setCopy.retainAll(items);
+        return set.size() > 0;
+    }
+
+    /** @return true if the specified set contains any item from the specified items */
+    public static <T> boolean containsAny(Set<T> set, T[] items)
+    {
+        Set<T> itemsSet = new HashSet<T>();
+        addAll(itemsSet, items);
+        return containsAny(set, itemsSet);
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index 7f8fd05e5d674804d8a71ca959e7f4e667c1e231..4c4ffc9c426db344e36fa21a75796b9fbcdea144 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -23,6 +23,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import javax.servlet.http.HttpSession;
 
@@ -109,6 +110,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory;
@@ -686,7 +688,8 @@ public final class CommonClientService extends AbstractClientService implements
                 public List<VocabularyTermWithStats> getOriginalData() throws UserFailureException
                 {
                     List<ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats> terms =
-                            commonServer.listVocabularyTerms(getSessionToken(), vocabulary);
+                            commonServer.listVocabularyTermsWithStatistics(getSessionToken(),
+                                    vocabulary);
                     return VocabularyTermTranslator.translate(terms);
                 }
             });
@@ -909,7 +912,7 @@ public final class CommonClientService extends AbstractClientService implements
         assert vocabularyCode != null : "Unspecified vocabulary code.";
         assert termsToBeDeleted != null : "Unspecified term to be deleted.";
         assert termsToBeReplaced != null : "Unspecified term to be replaced.";
-        
+
         try
         {
             final String sessionToken = getSessionToken();
@@ -921,6 +924,20 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public List<VocabularyTerm> listVocabularyTerms(Vocabulary vocabulary)
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            Set<VocabularyTermPE> terms =
+                    commonServer.listVocabularyTerms(sessionToken, vocabulary);
+            return VocabularyTermTranslator.translateTerms(terms);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public void registerProject(Project project)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/translator/VocabularyTermTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/translator/VocabularyTermTranslator.java
index f797f85667972f53923e356ba61fd759d57a3bee..dc4d714162594cad187c8b73a378ba8f6ed8e331 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/translator/VocabularyTermTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/translator/VocabularyTermTranslator.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.generic.client.web.server.translator;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.lang.StringEscapeUtils;
@@ -41,8 +42,18 @@ public class VocabularyTermTranslator
         return result;
     }
 
+    public static List<VocabularyTerm> translateTerms(Collection<VocabularyTermPE> terms)
+    {
+        List<VocabularyTerm> result = new ArrayList<VocabularyTerm>();
+        for (VocabularyTermPE term : terms)
+        {
+            result.add(translate(term));
+        }
+        return result;
+    }
+
     public static List<VocabularyTermWithStats> translate(
-            List<ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats> terms)
+            Collection<ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats> terms)
     {
         List<VocabularyTermWithStats> result = new ArrayList<VocabularyTermWithStats>();
         for (ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats term : terms)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index f1d001d77892df353af17ecc7926ef3190b20436..c30aa0c92c52f1344571cc2927367dbff7b36c76 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import org.springframework.dao.DataAccessException;
 
@@ -87,6 +88,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SearchHit;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
@@ -733,7 +735,7 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
 
     }
 
-    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+    public List<VocabularyTermWithStats> listVocabularyTermsWithStatistics(String sessionToken,
             Vocabulary vocabulary)
     {
         final Session session = getSessionManager().getSession(sessionToken);
@@ -742,6 +744,14 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
         return vocabularyBO.countTermsUsageStatistics();
     }
 
+    public Set<VocabularyTermPE> listVocabularyTerms(String sessionToken, Vocabulary vocabulary)
+    {
+        final Session session = getSessionManager().getSession(sessionToken);
+        final IVocabularyBO vocabularyBO = businessObjectFactory.createVocabularyBO(session);
+        vocabularyBO.load(vocabulary.getCode());
+        return vocabularyBO.enrichWithTerms();
+    }
+
     public List<DataSetTypePE> listDataSetTypes(String sessionToken)
     {
         return listEntityTypes(sessionToken, EntityKind.DATA_SET);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index 41bfbca184ab58130a0f7262b3dd49ee2b11eff2..75c4ca442b3e88177c03f788e28bd5f24e475c66 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import ch.systemsx.cisd.authentication.ISessionManager;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
@@ -59,6 +60,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SearchHit;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
@@ -366,8 +368,15 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
 
     }
 
-    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+    public List<VocabularyTermWithStats> listVocabularyTermsWithStatistics(String sessionToken,
             Vocabulary vocabulary)
+    {
+        logAccess(sessionToken, "list_vocabulary_terms_with_statistics", "VOCABULARY(%s)",
+                vocabulary.getCode());
+        return null;
+    }
+
+    public Set<VocabularyTermPE> listVocabularyTerms(String sessionToken, Vocabulary vocabulary)
     {
         logAccess(sessionToken, "list_vocabulary_terms", "VOCABULARY(%s)", vocabulary.getCode());
         return null;
@@ -384,4 +393,5 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         logAccess(sessionToken, "getLastModificationState");
         return null;
     }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
index 58e95ec10433c4733b0572179fedd26422304ab7..19e35fda4de2943c666367d8fa4bd453822ab835 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IVocabularyBO.java
@@ -17,12 +17,14 @@
 package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
 import java.util.List;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 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;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats;
 
 /**
@@ -41,27 +43,30 @@ public interface IVocabularyBO extends IBusinessObject
      * 
      * @throws UserFailureException if given <var>vocabulary</var> does already exist.
      */
-    public void define(final Vocabulary vocabulary) throws UserFailureException;
+    void define(final Vocabulary vocabulary) throws UserFailureException;
 
     /**
      * Returns the loaded {@link VocabularyPE}.
      */
-    public VocabularyPE getVocabulary();
+    VocabularyPE getVocabulary();
 
     /**
      * Loads specified vocabulary from the database.
      * 
      * @throws UserFailureException if no vocabulary found for <code>vocabularyCode</code>.
      */
-    public void load(String vocabularyCode) throws UserFailureException;
+    void load(String vocabularyCode) throws UserFailureException;
 
     /** @return terms with their usage statistics for the loaded vocabulary */
-    public List<VocabularyTermWithStats> countTermsUsageStatistics();
-    
+    List<VocabularyTermWithStats> countTermsUsageStatistics();
+
+    /** enriches currently loaded vocabulary with its terms and returns them */
+    Set<VocabularyTermPE> enrichWithTerms();
+
     /**
      * Add the specified terms to a loaded vocabulary.
      */
-    public void addNewTerms(List<String> newTerms);
+    void addNewTerms(List<String> newTerms);
 
     /**
      * Deletes the specified terms from a loaded vocabulary and replaces terms which are used.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
index 7c4fc77e3fa2d9034842edd2bbd3f5e42c7e0e8f..16e381cb93f34b8744242849e92598c15ffa6b80 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/VocabularyBO.java
@@ -206,8 +206,9 @@ public class VocabularyBO extends AbstractBusinessObject implements IVocabularyB
         }
     }
 
-    private void enrichWithTerms()
+    public Set<VocabularyTermPE> enrichWithTerms()
     {
         HibernateUtils.initialize(vocabularyPE.getTerms());
+        return vocabularyPE.getTerms();
     }
 }
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 b4aa3e9fc8d6f49879b080d5279da6280ddf6b83..39afa5a49651bfcba27a282f52685bbef1aab011 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
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.shared;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import org.springframework.transaction.annotation.Transactional;
 
@@ -67,6 +68,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchHit;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
@@ -315,6 +317,7 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
     public void deleteVocabularyTerms(String sessionToken, String vocabularyCode,
             List<VocabularyTerm> termsToBeDeleted, List<VocabularyTermReplacement> termsToBeReplaced);
 
@@ -437,11 +440,18 @@ public interface ICommonServer extends IServer
     /**
      * Lists vocabulary terms of a given vocabulary. Includes terms usage statistics.
      */
-    @Transactional
-    @RolesAllowed(RoleSet.USER)
-    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<VocabularyTermWithStats> listVocabularyTermsWithStatistics(String sessionToken,
             Vocabulary vocabulary);
 
+    /**
+     * Lists vocabulary terms of a given vocabulary.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public Set<VocabularyTermPE> listVocabularyTerms(String sessionToken, Vocabulary vocabulary);
+
     /**
      * List data set types.
      * 
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 e823e8196dce7eeab7299dcc54d22ac1297d060c..d1a0972c53c4875013c26a53a87bb78a53f3f017 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
@@ -16,6 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
@@ -25,11 +28,13 @@ import com.google.gwt.user.client.rpc.IsSerializable;
  */
 public class DatabaseModificationKind implements IsSerializable
 {
+    public static final DatabaseModificationKind[] EMPTY_ARRAY = new DatabaseModificationKind[0];
+
     public enum ObjectKind implements IsSerializable
     {
-        SAMPLE, EXPERIMENT, MATERIAL, SAMPLE_TYPE, EXPERIMENT_TYPE, MATERIAL_TYPE, PROJECT, GROUP,
-        DATA_SET, PROPERTY_TYPE, PROPERTY_TYPE_ASSIGNMENT, VOCABULARY, VOCABULARY_TERM, ROLE,
-        PERSON
+        SAMPLE, EXPERIMENT, MATERIAL, DATA_SET, SAMPLE_TYPE, EXPERIMENT_TYPE, MATERIAL_TYPE,
+        DATASET_TYPE, PROJECT, GROUP, PROPERTY_TYPE, PROPERTY_TYPE_ASSIGNMENT, VOCABULARY,
+        VOCABULARY_TERM, ROLE, PERSON
     }
 
     public enum OperationKind implements IsSerializable
@@ -49,6 +54,14 @@ public class DatabaseModificationKind implements IsSerializable
     {
     }
 
+    public static final DatabaseModificationKind[] any(ObjectKind objectType)
+    {
+        List<DatabaseModificationKind> result = new ArrayList<DatabaseModificationKind>();
+        result.add(createOrDelete(objectType));
+        result.add(edit(objectType));
+        return result.toArray(EMPTY_ARRAY);
+    }
+
     public static final DatabaseModificationKind createOrDelete(ObjectKind objectType)
     {
         return new DatabaseModificationKind(objectType, OperationKind.CREATE_OR_DELETE);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityEditForm.java
index 5665178b6529956a0e1f88fd15addbc2cdea3cf1..6f2bcf921cc984b433f261d87dca88ae5d14940f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityEditForm.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import com.extjs.gxt.ui.client.util.Margins;
 import com.extjs.gxt.ui.client.widget.form.Field;
@@ -28,8 +29,12 @@ import com.google.gwt.user.client.ui.Widget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 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.framework.CompositeDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.IEditableEntity;
+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;
@@ -43,7 +48,7 @@ import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.exp
  * @author Izabela Adamczyk
  */
 abstract public class AbstractGenericEntityEditForm<T extends EntityType, S extends EntityTypePropertyType<T>, P extends EntityProperty<T, S>, V extends IEditableEntity<T, S, P>>
-        extends AbstractRegistrationForm
+        extends AbstractRegistrationForm implements IDatabaseModificationObserver
 {
 
     private final PropertiesEditor<T, S, P> editor;
@@ -58,7 +63,7 @@ abstract public class AbstractGenericEntityEditForm<T extends EntityType, S exte
 
     abstract protected List<Widget> getEntitySpecificCheckPageWidgets();
 
-    abstract protected List<Field<?>> getEntitySpecificFormFields();
+    abstract protected List<DatabaseModificationAwareField<?>> getEntitySpecificFormFields();
 
     abstract protected void updateCheckPageWidgets();
 
@@ -87,35 +92,12 @@ abstract public class AbstractGenericEntityEditForm<T extends EntityType, S exte
         {
             checkComponents.add(w);
         }
-        // TODO 2009-03-18, Tomasz Pylak: Uncomment when LMS-794 is closed 
-        //checkComponents.add(createEditorButton(viewContext));
         for (Widget w : checkComponents)
         {
             add(w, new RowData(1, -1, new Margins(5)));
         }
     }
 
-    // TODO 2009-03-18, Tomasz Pylak: Uncomment when LMS-794 is closed 
-//    private Button createEditorButton(final IViewContext<?> viewContext)
-//    {
-//        return new Button(viewContext.getMessage(Dict.BUTTON_EDIT),
-//                new SelectionListener<ComponentEvent>()
-//                    {
-//                        @Override
-//                        public void componentSelected(ComponentEvent ce)
-//                        {
-//                            showEditor();
-//                        }
-//                    });
-//    }
-//
-//    protected void showEditor()
-//    {
-//        setEditMode(true);
-//        infoBox.reset();
-//        formPanel.reset();
-//    }
-
     protected static String createId(EntityKind entityKind, String identifier)
     {
         return GenericConstants.ID_PREFIX + createSimpleId(entityKind, identifier);
@@ -126,15 +108,26 @@ abstract public class AbstractGenericEntityEditForm<T extends EntityType, S exte
         return "generic-" + entityKind.name().toLowerCase() + "-edit_form_" + identifier;
     }
 
-    private final void addFormFields()
+    private final List<DatabaseModificationAwareField<?>> getAllFields()
     {
-        for (final Field<?> propertyField : editor.getPropertyFields())
+        List<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
+        for (DatabaseModificationAwareField<?> specificField : editor.getPropertyFields())
         {
-            formPanel.add(propertyField);
+            fields.add(specificField);
         }
-        for (final Field<?> specificField : getEntitySpecificFormFields())
+        for (DatabaseModificationAwareField<?> propertyField : getEntitySpecificFormFields())
         {
-            formPanel.add(specificField);
+            fields.add(propertyField);
+        }
+        return fields;
+    }
+
+    private final void addFormFields()
+    {
+        for (DatabaseModificationAwareField<?> field : getAllFields())
+        {
+            formPanel.add(field.get());
         }
     }
 
@@ -167,16 +160,40 @@ abstract public class AbstractGenericEntityEditForm<T extends EntityType, S exte
         setEditMode(false);
     }
 
-    @SuppressWarnings("unchecked")
     protected void updateState()
     {
-        for (Field f : editor.getPropertyFields())
+        for (DatabaseModificationAwareField<?> f : editor.getPropertyFields())
         {
-            f.updateOriginalValue(f.getValue());
+            updateOriginalValue(f.get());
         }
         entity.setProperties(editor.extractProperties());
         grid.setProperties(entity.getProperties());
         updateCheckPageWidgets();
     }
 
+    @SuppressWarnings("unchecked")
+    private void updateOriginalValue(Field field)
+    {
+        field.updateOriginalValue(field.getValue());
+    }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        createDatabaseModificationObserver().update(observedModifications);
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return createDatabaseModificationObserver().getRelevantModifications();
+    }
+
+    // the db modification observer is composed from all the fields' observers
+    private IDatabaseModificationObserver createDatabaseModificationObserver()
+    {
+        CompositeDatabaseModificationObserver compositeObserver =
+                new CompositeDatabaseModificationObserver();
+        compositeObserver.addObservers(getAllFields());
+        return compositeObserver;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
index 6a66ffc8b4d7534980a2f367dce5031cf6c7d415..b4fd8dd1419b3ad32816c28554133a7744446f40 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java
@@ -16,9 +16,10 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
-import com.extjs.gxt.ui.client.widget.form.Field;
 import com.extjs.gxt.ui.client.widget.form.TextField;
 import com.google.gwt.user.client.Element;
 
@@ -26,8 +27,12 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 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.framework.CompositeDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.CodeField;
+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;
@@ -41,7 +46,7 @@ import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.exp
  * @author Izabela Adamczyk
  */
 abstract public class AbstractGenericEntityRegistrationForm<T extends EntityType, S extends EntityTypePropertyType<T>, P extends EntityProperty<T, S>>
-        extends AbstractRegistrationForm
+        extends AbstractRegistrationForm implements IDatabaseModificationObserver
 {
 
     public static final String ID_SUFFIX_CODE = "code";
@@ -63,7 +68,7 @@ abstract public class AbstractGenericEntityRegistrationForm<T extends EntityType
                         .getCommonViewContext());
     }
 
-    abstract protected List<Field<?>> getEntitySpecificFields();
+    abstract protected List<DatabaseModificationAwareField<?>> getEntitySpecificFields();
 
     abstract protected void createEntitySpecificFields();
 
@@ -88,16 +93,27 @@ abstract public class AbstractGenericEntityRegistrationForm<T extends EntityType
         createEntitySpecificFields();
     }
 
-    private final void addFormFields()
+    private final List<DatabaseModificationAwareField<?>> getAllFields()
     {
-        formPanel.add(codeField);
-        for (final Field<?> specificField : getEntitySpecificFields())
+        List<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
+        fields.add(DatabaseModificationAwareField.wrapUnaware(codeField));
+        for (DatabaseModificationAwareField<?> specificField : getEntitySpecificFields())
+        {
+            fields.add(specificField);
+        }
+        for (DatabaseModificationAwareField<?> propertyField : propertiesEditor.getPropertyFields())
         {
-            formPanel.add(specificField);
+            fields.add(propertyField);
         }
-        for (final Field<?> propertyField : propertiesEditor.getPropertyFields())
+        return fields;
+    }
+
+    private final void addFormFields()
+    {
+        for (DatabaseModificationAwareField<?> field : getAllFields())
         {
-            formPanel.add(propertyField);
+            formPanel.add(field.get());
         }
     }
 
@@ -113,4 +129,23 @@ abstract public class AbstractGenericEntityRegistrationForm<T extends EntityType
         createFormFields();
         addFormFields();
     }
+
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        createDatabaseModificationObserver().update(observedModifications);
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return createDatabaseModificationObserver().getRelevantModifications();
+    }
+
+    // the db modification observer is composed from all the fields' observers
+    private IDatabaseModificationObserver createDatabaseModificationObserver()
+    {
+        CompositeDatabaseModificationObserver compositeObserver =
+                new CompositeDatabaseModificationObserver();
+        compositeObserver.addObservers(getAllFields());
+        return compositeObserver;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
index db98ff05265563a93e15706964a0f68f2f265a32..dd1415a77dca2d3b82debb76c217185270a4d266 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java
@@ -18,13 +18,14 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application;
 
 import java.util.Set;
 
-import com.extjs.gxt.ui.client.widget.Component;
 import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractClientPluginFactory;
 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.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DefaultTabItem;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItem;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItemFactory;
@@ -161,9 +162,12 @@ public final class ClientPluginFactory extends
                 };
         }
 
-        public final Widget createRegistrationForEntityType(final SampleType sampleType)
+        public final DatabaseModificationAwareWidget createRegistrationForEntityType(
+                final SampleType sampleType)
         {
-            return new GenericSampleRegistrationForm(getViewContext(), sampleType);
+            GenericSampleRegistrationForm form =
+                    new GenericSampleRegistrationForm(getViewContext(), sampleType);
+            return new DatabaseModificationAwareWidget(form, form);
         }
 
         public final Widget createBatchRegistrationForEntityType(final SampleType sampleType)
@@ -177,10 +181,10 @@ public final class ClientPluginFactory extends
                 {
                     public ITabItem create()
                     {
-                        Component component =
-                                new GenericSampleEditForm(getViewContext(), entity, true);
-                        return new DefaultTabItem(
-                                getEditTitle(Dict.SAMPLE, entity.getIdentifier()), component, true);
+                        DatabaseModificationAwareComponent component =
+                                GenericSampleEditForm.create(getViewContext(), entity, true);
+                        String title = getEditTitle(Dict.SAMPLE, entity.getIdentifier());
+                        return DefaultTabItem.create(title, component, getViewContext(), true);
                     }
 
                     public String getId()
@@ -231,10 +235,10 @@ public final class ClientPluginFactory extends
                 {
                     public ITabItem create()
                     {
-                        Component component =
-                                new GenericMaterialEditForm(getViewContext(), entity, true);
-                        return new DefaultTabItem(getEditTitle(Dict.MATERIAL, entity
-                                .getIdentifier()), component, true);
+                        DatabaseModificationAwareComponent component =
+                                GenericMaterialEditForm.create(getViewContext(), entity, true);
+                        String title = getEditTitle(Dict.MATERIAL, entity.getIdentifier());
+                        return DefaultTabItem.create(title, component, getViewContext(), true);
                     }
 
                     public String getId()
@@ -276,9 +280,12 @@ public final class ClientPluginFactory extends
         }
 
         @Override
-        public Widget createRegistrationForEntityType(ExperimentType entityType)
+        public DatabaseModificationAwareWidget createRegistrationForEntityType(
+                ExperimentType entityType)
         {
-            return new GenericExperimentRegistrationForm(getViewContext(), entityType);
+            GenericExperimentRegistrationForm form =
+                    new GenericExperimentRegistrationForm(getViewContext(), entityType);
+            return new DatabaseModificationAwareWidget(form, form);
         }
 
         @Override
@@ -288,10 +295,10 @@ public final class ClientPluginFactory extends
                 {
                     public ITabItem create()
                     {
-                        Component component =
-                                new GenericExperimentEditForm(getViewContext(), entity, true);
-                        return new DefaultTabItem(getEditTitle(Dict.EXPERIMENT, entity
-                                .getIdentifier()), component, true);
+                        DatabaseModificationAwareComponent component =
+                                GenericExperimentEditForm.create(getViewContext(), entity, true);
+                        String title = getEditTitle(Dict.EXPERIMENT, entity.getIdentifier());
+                        return DefaultTabItem.create(title, component, getViewContext(), true);
                     }
 
                     public String getId()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
index c1aba1aec3147c5bdb0f088ab093353c1488d54d..a7e64e44567fa6666ec69c14cce1266a187ded2c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentEditForm.java
@@ -24,7 +24,6 @@ import com.extjs.gxt.ui.client.event.ButtonEvent;
 import com.extjs.gxt.ui.client.event.SelectionListener;
 import com.extjs.gxt.ui.client.util.Format;
 import com.extjs.gxt.ui.client.widget.Html;
-import com.extjs.gxt.ui.client.widget.form.Field;
 import com.extjs.gxt.ui.client.widget.form.FileUploadField;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -32,6 +31,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAs
 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.client.web.client.application.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.EditableExperiment;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment.ProjectSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
@@ -69,7 +70,16 @@ public final class GenericExperimentEditForm
 
     private String originalProjectIdentifier;
 
-    public GenericExperimentEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
+    public static DatabaseModificationAwareComponent create(
+            IViewContext<IGenericClientServiceAsync> viewContext, EditableExperiment entity,
+            boolean editMode)
+    {
+        GenericExperimentEditForm form =
+                new GenericExperimentEditForm(viewContext, entity, editMode);
+        return new DatabaseModificationAwareComponent(form, form);
+    }
+
+    private GenericExperimentEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
             EditableExperiment entity, boolean editMode)
     {
         super(viewContext, entity, editMode);
@@ -174,14 +184,16 @@ public final class GenericExperimentEditForm
         return new ExperimentPropertyEditor(entityTypesPropertyTypes, properties, id, context);
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    protected List<Field<?>> getEntitySpecificFormFields()
+    protected List<DatabaseModificationAwareField<?>> getEntitySpecificFormFields()
     {
-        List<Field<?>> fields = new ArrayList<Field<?>>();
-        fields.add(projectChooser);
+        List<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
+        fields.add(projectChooser.asDatabaseModificationAware());
         for (FileUploadField f : attachmentManager.getFields())
         {
-            fields.add(f);
+            fields.add(DatabaseModificationAwareField.wrapUnaware(f));
         }
         return fields;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java
index aafe5a264ea814c60bdbd6ccd8fbf82a35d194d5..0c82099888293027bcbd58833d1dd7abaefe4dcf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -31,6 +33,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAs
 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.client.web.client.application.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment.ProjectSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils;
@@ -197,14 +200,15 @@ public final class GenericExperimentRegistrationForm
     }
 
     @Override
-    protected List<Field<?>> getEntitySpecificFields()
+    protected List<DatabaseModificationAwareField<?>> getEntitySpecificFields()
     {
-        final ArrayList<Field<?>> fields = new ArrayList<Field<?>>();
-        fields.add(projectSelectionWidget);
-        fields.add(samplesArea);
+        final ArrayList<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
+        fields.add(projectSelectionWidget.asDatabaseModificationAware());
+        fields.add(wrapUnaware(samplesArea));
         for (FileUploadField attachmentField : attachmentManager.getFields())
         {
-            fields.add(attachmentField);
+            fields.add(wrapUnaware((Field<?>) attachmentField));
         }
         return fields;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java
index 1e0081e22fd6f10d43e961471a89e0f6a365d68d..d5c40ba43bed2e0bcd2b5fabcea7da20bd55e18c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java
@@ -21,10 +21,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import com.extjs.gxt.ui.client.widget.form.Field;
-
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.PropertyFieldFactory;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
@@ -40,7 +39,7 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp
 
     private final List<S> entityTypesPropertyTypes;
 
-    private final List<Field<?>> propertyFields;
+    private final List<DatabaseModificationAwareField<?>> propertyFields;
 
     private final String id;
 
@@ -61,9 +60,11 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp
         this.propertyFields = createPropertyFields(viewContext);
     }
 
-    private List<Field<?>> createPropertyFields(IViewContext<ICommonClientServiceAsync> viewContext)
+    private List<DatabaseModificationAwareField<?>> createPropertyFields(
+            IViewContext<ICommonClientServiceAsync> viewContext)
     {
-        List<Field<?>> result = new ArrayList<Field<?>>();
+        List<DatabaseModificationAwareField<?>> result =
+                new ArrayList<DatabaseModificationAwareField<?>>();
         for (final S stpt : entityTypesPropertyTypes)
         {
             result.add(createPropertyField(stpt, initialProperties.get(stpt.getPropertyType()
@@ -91,18 +92,18 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp
         this(id, entityTypesPropertyTypes, new ArrayList<P>(), viewContext);
     }
 
-    private final Field<?> createPropertyField(final S etpt, String value,
+    private final DatabaseModificationAwareField<?> createPropertyField(final S etpt, String value,
             IViewContext<ICommonClientServiceAsync> viewContext)
     {
-        final Field<?> field;
+        final DatabaseModificationAwareField<?> field;
         final boolean isMandatory = etpt.isMandatory();
         final String label = etpt.getPropertyType().getLabel();
         final String propertyTypeCode = etpt.getPropertyType().getCode();
         field =
                 PropertyFieldFactory.createField(etpt.getPropertyType(), isMandatory, label,
                         createFormFieldId(getId(), propertyTypeCode), value, viewContext);
-        field.setData(ETPT, etpt);
-        field.setTitle(propertyTypeCode);
+        field.get().setData(ETPT, etpt);
+        field.get().setTitle(propertyTypeCode);
         return field;
     }
 
@@ -122,14 +123,14 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp
     public final List<P> extractProperties()
     {
         final List<P> properties = new ArrayList<P>();
-        for (final Field<?> field : propertyFields)
+        for (final DatabaseModificationAwareField<?> field : propertyFields)
         {
-            if (field.getValue() != null
-                    && PropertyFieldFactory.valueToString(field.getValue()) != null)
+            Object value = field.get().getValue();
+            if (value != null && PropertyFieldFactory.valueToString(value) != null)
             {
-                final S stpt = field.getData(ETPT);
+                final S stpt = field.get().getData(ETPT);
                 final P sampleProperty = createEntityProperty();
-                sampleProperty.setValue(PropertyFieldFactory.valueToString(field.getValue()));
+                sampleProperty.setValue(PropertyFieldFactory.valueToString(value));
                 sampleProperty.setEntityTypePropertyType(stpt);
                 properties.add(sampleProperty);
             }
@@ -141,7 +142,7 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp
      * Returns a list of fields appropriate for entity type - property type assignments specific to
      * given {@link PropertiesEditor}.
      */
-    public final List<Field<?>> getPropertyFields()
+    public final List<DatabaseModificationAwareField<?>> getPropertyFields()
     {
         return propertyFields;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java
index a7a8b045d893519d8e7276f6365b9caa12989575..b72b52e97ed66bec930e92e75126ee2ab2fee151 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java
@@ -19,13 +19,14 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.ma
 import java.util.ArrayList;
 import java.util.List;
 
-import com.extjs.gxt.ui.client.widget.form.Field;
 import com.google.gwt.user.client.ui.Widget;
 
 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.client.web.client.application.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.EditableMaterial;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialProperty;
@@ -47,7 +48,15 @@ public final class GenericMaterialEditForm
 
     private final IViewContext<IGenericClientServiceAsync> viewContext;
 
-    public GenericMaterialEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
+    public static DatabaseModificationAwareComponent create(
+            IViewContext<IGenericClientServiceAsync> viewContext, EditableMaterial entity,
+            boolean editMode)
+    {
+        GenericMaterialEditForm form = new GenericMaterialEditForm(viewContext, entity, editMode);
+        return new DatabaseModificationAwareComponent(form, form);
+    }
+
+    private GenericMaterialEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
             EditableMaterial entity, boolean editMode)
     {
         super(viewContext, entity, editMode);
@@ -96,9 +105,9 @@ public final class GenericMaterialEditForm
     }
 
     @Override
-    protected List<Field<?>> getEntitySpecificFormFields()
+    protected List<DatabaseModificationAwareField<?>> getEntitySpecificFormFields()
     {
-        return new ArrayList<Field<?>>();
+        return new ArrayList<DatabaseModificationAwareField<?>>();
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java
index 9b18429e7dd9d8e25e52a81315ccb7c24ed34f53..28887c6a8e08063b3f6574d07513c6dd3fcab41e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java
@@ -16,12 +16,13 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import com.extjs.gxt.ui.client.widget.form.Field;
 import com.google.gwt.user.client.ui.Widget;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
@@ -29,6 +30,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAs
 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.client.web.client.application.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.EditableSample;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.ExperimentChooserField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.ExperimentChooserField.ExperimentChooserFieldAdaptor;
@@ -62,7 +65,15 @@ public final class GenericSampleEditForm
 
     private final IViewContext<IGenericClientServiceAsync> viewContext;
 
-    public GenericSampleEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
+    public static DatabaseModificationAwareComponent create(
+            IViewContext<IGenericClientServiceAsync> viewContext, EditableSample entity,
+            boolean editMode)
+    {
+        GenericSampleEditForm form = new GenericSampleEditForm(viewContext, entity, editMode);
+        return new DatabaseModificationAwareComponent(form, form);
+    }
+    
+    private GenericSampleEditForm(IViewContext<IGenericClientServiceAsync> viewContext,
             EditableSample entity, boolean editMode)
     {
         super(viewContext, entity, editMode);
@@ -125,12 +136,13 @@ public final class GenericSampleEditForm
     }
 
     @Override
-    protected List<Field<?>> getEntitySpecificFormFields()
+    protected List<DatabaseModificationAwareField<?>> getEntitySpecificFormFields()
     {
-        ArrayList<Field<?>> fields = new ArrayList<Field<?>>();
+        ArrayList<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
         if (experimentFieldOrNull != null)
         {
-            fields.add(experimentFieldOrNull.getField());
+            fields.add(wrapUnaware(experimentFieldOrNull.getField()));
         }
         return fields;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
index 7fd4c349082de67343922e1afc18dfa75677860a..287343c8d74dcdb1e875f2185fe3f62b560f51f0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java
@@ -16,10 +16,11 @@
 
 package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField.wrapUnaware;
+
 import java.util.ArrayList;
 import java.util.List;
 
-import com.extjs.gxt.ui.client.widget.form.Field;
 import com.extjs.gxt.ui.client.widget.form.TextField;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
@@ -27,6 +28,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAs
 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.client.web.client.application.InfoBoxCallbackListener;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.VarcharField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
@@ -145,12 +147,13 @@ public final class GenericSampleRegistrationForm extends
     }
 
     @Override
-    protected List<Field<?>> getEntitySpecificFields()
+    protected List<DatabaseModificationAwareField<?>> getEntitySpecificFields()
     {
-        List<Field<?>> fields = new ArrayList<Field<?>>();
-        fields.add(groupSelectionWidget);
-        fields.add(parent);
-        fields.add(container);
+        List<DatabaseModificationAwareField<?>> fields =
+                new ArrayList<DatabaseModificationAwareField<?>>();
+        fields.add(groupSelectionWidget.asDatabaseModificationAware());
+        fields.add(wrapUnaware(parent));
+        fields.add(wrapUnaware(container));
         return fields;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ClientPluginFactory.java
index 38bb0ebb8cd9425f73b0c9e7a88e417e716e5afe..93052f82c20263f7996bfba6a5380a7a5d2cc6f9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ClientPluginFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/ClientPluginFactory.java
@@ -25,6 +25,7 @@ import com.google.gwt.user.client.ui.Widget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractClientPluginFactory;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DatabaseModificationAwareWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DefaultTabItem;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.DummyComponent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.ITabItem;
@@ -138,9 +139,10 @@ public final class ClientPluginFactory extends
                 };
         }
 
-        public final Widget createRegistrationForEntityType(final SampleType sampleTypeCode)
+        public final DatabaseModificationAwareWidget createRegistrationForEntityType(
+                final SampleType sampleTypeCode)
         {
-            return new DummyComponent();
+            return DatabaseModificationAwareWidget.wrapUnaware(new DummyComponent());
         }
 
         public final Widget createBatchRegistrationForEntityType(final SampleType sampleType)
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 ebaa7f070166032da392594ab48fbdcd9317d452..43ff1e8f3598ebeb0c24080bcf5ad8a0a5f32e5d 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
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.shared;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import org.springframework.transaction.annotation.Transactional;
 
@@ -67,6 +68,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchHit;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.DatabaseInstanceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier;
@@ -315,6 +317,7 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
     public void deleteVocabularyTerms(String sessionToken, String vocabularyCode,
             List<VocabularyTerm> termsToBeDeleted, List<VocabularyTermReplacement> termsToBeReplaced);
 
@@ -437,11 +440,18 @@ public interface ICommonServer extends IServer
     /**
      * Lists vocabulary terms of a given vocabulary. Includes terms usage statistics.
      */
-    @Transactional
-    @RolesAllowed(RoleSet.USER)
-    public List<VocabularyTermWithStats> listVocabularyTerms(String sessionToken,
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public List<VocabularyTermWithStats> listVocabularyTermsWithStatistics(String sessionToken,
             Vocabulary vocabulary);
 
+    /**
+     * Lists vocabulary terms of a given vocabulary.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.OBSERVER)
+    public Set<VocabularyTermPE> listVocabularyTerms(String sessionToken, Vocabulary vocabulary);
+
     /**
      * List data set types.
      *