diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index 15a89de3e3897e9f846a981d839d37f7ac00fa21..cf67253ddf7aba7cd6d5ebfbfcc2bd5eb7350e11 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -149,6 +149,8 @@ public abstract class Dict
 
     public static final String BUTTON_RESET = "button_reset";
 
+    public static final String BUTTON_REVERT = "button_revert";
+
     public static final String BUTTON_SUBMIT = "button_submit";
 
     public static final String BUTTON_REFRESH = "button_refresh";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentWithCloseConfirmationUtil.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentWithCloseConfirmationUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c27e1765fc2031a17cdc55be0b2d49d6b7a2993
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentWithCloseConfirmationUtil.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 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;
+
+/**
+ * @author pkupczyk
+ */
+public class ComponentWithCloseConfirmationUtil
+{
+
+    public static boolean isComponentWithCloseConfirmation(Object object)
+    {
+        return object instanceof IComponentWithCloseConfirmation;
+    }
+
+    public static IComponentWithCloseConfirmation asComponentWithCloseConfirmation(Object object)
+    {
+        if (isComponentWithCloseConfirmation(object))
+        {
+            return (IComponentWithCloseConfirmation) object;
+        } else
+        {
+            return null;
+        }
+    }
+
+    public static boolean shouldAskForCloseConfirmation(Object object)
+    {
+        if (isComponentWithCloseConfirmation(object))
+        {
+            return asComponentWithCloseConfirmation(object).shouldAskForCloseConfirmation();
+        } else
+        {
+            return false;
+        }
+    }
+
+}
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 b7d5050f995f1364dae379823be8bb80fdcb7a6b..2b482de78be272589a6e8474120c500be29668ed 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
@@ -38,14 +38,14 @@ public class DefaultTabItem implements ITabItem
 
     private final IDelegatedAction disposerActionOrNull;
 
-    private final boolean isCloseConfirmationNeeded;
-
     private final LastModificationStateUpdater lastModificationStateUpdaterOrNull;
 
     private final LastHistoryTokenUpdater historyTokenUpdater;
 
     private final IDelegatedAction updaterOrNull;
 
+    private final boolean isCloseConfirmationNeeded;
+
     /**
      * Creates a tab with the specified {@link Component}. The tab is unaware of database
      * modifications and will not be automatically refreshed if changes occur.
@@ -67,7 +67,7 @@ public class DefaultTabItem implements ITabItem
     {
         return new DefaultTabItem(viewContext, title, component, updater, null, null, false);
     }
-    
+
     /**
      * Creates a tab with the specified {@link ContentPanel}. The tab is unaware of database
      * modifications and will not be automatically refreshed if changes occur.
@@ -114,7 +114,8 @@ public class DefaultTabItem implements ITabItem
     }
 
     private static DefaultTabItem create(IViewContext<?> viewContext, final String title,
-            final Component component, IDelegatedAction updaterOrNull, IDatabaseModificationObserver modificationObserver,
+            final Component component, IDelegatedAction updaterOrNull,
+            IDatabaseModificationObserver modificationObserver,
             IDelegatedAction disposerActionOrNull, boolean isCloseConfirmationNeeded)
     {
         LastModificationStateUpdater stateUpdater =
@@ -148,10 +149,7 @@ public class DefaultTabItem implements ITabItem
         this.component = component;
         this.lastModificationStateUpdaterOrNull = lastModificationStateUpdaterOrNull;
         this.disposerActionOrNull = disposerActionOrNull;
-        // TODO 2009-05-08, Tomasz Pylak: uncomment this when confirmation will be asked only in
-        // relevant moments.
-        // this.isCloseConfirmationNeeded = isCloseConfirmationNeeded;
-        this.isCloseConfirmationNeeded = false;
+        this.isCloseConfirmationNeeded = isCloseConfirmationNeeded;
     }
 
     //
@@ -172,7 +170,13 @@ public class DefaultTabItem implements ITabItem
     @Override
     public boolean isCloseConfirmationNeeded()
     {
-        return isCloseConfirmationNeeded;
+        if (isCloseConfirmationNeeded)
+        {
+            return ComponentWithCloseConfirmationUtil.shouldAskForCloseConfirmation(component);
+        } else
+        {
+            return false;
+        }
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IComponentWithCloseConfirmation.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IComponentWithCloseConfirmation.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0be8aca2ba65670e8ae92002d05da771975ea14
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/IComponentWithCloseConfirmation.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 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;
+
+/**
+ * Components that implement this interface and are added as tab contents can dynamically control
+ * whether closing the tab requires an additional confirmation.
+ * 
+ * @author pkupczyk
+ */
+public interface IComponentWithCloseConfirmation
+{
+
+    public boolean shouldAskForCloseConfirmation();
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
index 8122bf741e1d4dc9c8ed80a0c58f67f11219afe6..29e545a5e6a504d74bc9233554d0bf295e1c640b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/MainTabPanel.java
@@ -277,10 +277,7 @@ public class MainTabPanel extends TabPanel implements IMainPanel
             add(tabItem.getComponent());
             tabItem.getComponent().addListener(AppEvents.CloseViewer, createCloseViewerListener());
             tabItem.getTabTitleUpdater().bind(this);
-            if (tabItem.isCloseConfirmationNeeded())
-            {
-                addListener(Events.BeforeClose, createBeforeCloseListener());
-            }
+            addListener(Events.BeforeClose, createBeforeCloseListener());
             addListener(Events.Close, createCloseTabListener());
             addListener(Events.Select, createActivateTabListener());
         }
@@ -361,19 +358,25 @@ public class MainTabPanel extends TabPanel implements IMainPanel
         {
             return new Listener<TabPanelEvent>()
                 {
+                    private boolean closeConfirmed = false;
+
                     @Override
                     public void handleEvent(final TabPanelEvent be)
                     {
-                        be.setCancelled(true);
-                        new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE),
-                                viewContext.getMessage(Dict.CONFIRM_CLOSE_MSG))
-                            {
-                                @Override
-                                protected void onYes()
+                        if (tabItem.isCloseConfirmationNeeded() && closeConfirmed == false)
+                        {
+                            be.setCancelled(true);
+                            new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE),
+                                    viewContext.getMessage(Dict.CONFIRM_CLOSE_MSG))
                                 {
-                                    MainTabItem.this.close();
-                                }
-                            }.show();
+                                    @Override
+                                    protected void onYes()
+                                    {
+                                        closeConfirmed = true;
+                                        MainTabItem.this.close();
+                                    }
+                                }.show();
+                        }
                     }
                 };
         }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SpaceModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SpaceModel.java
index bc401a580e814a0e548657b626e92386e3c79065..fafe4f4ff456a88d5b797ead523d36c092131993 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SpaceModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/SpaceModel.java
@@ -59,4 +59,25 @@ public class SpaceModel extends SimplifiedBaseModelData
     {
         return get(ModelDataPropertyNames.OBJECT);
     }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == this)
+        {
+            return true;
+        }
+        if (obj instanceof SpaceModel == false)
+        {
+            return false;
+        }
+        final SpaceModel that = (SpaceModel) obj;
+        if (getBaseObject() == null)
+        {
+            return that.getBaseObject() == null;
+        } else
+        {
+            return getBaseObject().equals(that.getBaseObject());
+        }
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
index 78c121304fc124ff2c371316170d02a3748504c2..fbf42e8887d42714b1720a8dea67f46956c11fcf 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AbstractRegistrationForm.java
@@ -21,7 +21,9 @@ import java.util.List;
 
 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.Events;
 import com.extjs.gxt.ui.client.event.FieldEvent;
 import com.extjs.gxt.ui.client.event.Listener;
 import com.extjs.gxt.ui.client.event.SelectionListener;
@@ -44,7 +46,10 @@ 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.ui.widget.ClickableFormPanel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IComponentWithCloseConfirmation;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.ConfirmationDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FormPanelWithSavePoint;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FormPanelWithSavePoint.DirtyChangeEvent;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.InfoBox;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.WidgetUtils;
@@ -55,8 +60,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IIdAndCodeHolder;
  * 
  * @author Christian Ribeaud
  */
-public abstract class AbstractRegistrationForm extends ContentPanel
+public abstract class AbstractRegistrationForm extends ContentPanel implements
+        IComponentWithCloseConfirmation
 {
+
     public static final int PANEL_MARGIN = 100;
 
     private static final String SESSION_KEY_PREFIX = "sessionKey_";
@@ -77,9 +84,11 @@ public abstract class AbstractRegistrationForm extends ContentPanel
 
     public static final int SECTION_WIDTH = SECTION_FIELD_WIDTH + SECTION_LABEL_WIDTH + 70;// +16
 
+    protected IMessageProvider messageProvider;
+
     protected InfoBox infoBox;
 
-    protected FormPanel formPanel;
+    protected FormPanelWithSavePoint formPanel;
 
     protected final int labelWidth;
 
@@ -95,6 +104,8 @@ public abstract class AbstractRegistrationForm extends ContentPanel
 
     private Button resetButton;
 
+    private Button revertButton;
+
     protected AbstractRegistrationForm(final IMessageProvider messageProvider, final String id)
     {
         this(messageProvider, id, DEFAULT_LABEL_WIDTH, DEFAULT_FIELD_WIDTH);
@@ -103,6 +114,7 @@ public abstract class AbstractRegistrationForm extends ContentPanel
     protected AbstractRegistrationForm(final IMessageProvider messageProvider, final String id,
             final int labelWidth, final int fieldWidth)
     {
+        this.messageProvider = messageProvider;
         this.labelWidth = labelWidth;
         this.fieldWidth = fieldWidth;
         setHeaderVisible(false);
@@ -113,8 +125,7 @@ public abstract class AbstractRegistrationForm extends ContentPanel
         setId(id);
         add(infoBox = createInfoBox());
         add(loadingInfo = createLoadingInfo());
-        add(WidgetUtils.inRow(formPanel = createFormPanel(messageProvider), rightPanel =
-                createAdditionalPanel()));
+        add(WidgetUtils.inRow(formPanel = createFormPanel(), rightPanel = createAdditionalPanel()));
     }
 
     private LayoutContainer createAdditionalPanel()
@@ -146,14 +157,53 @@ public abstract class AbstractRegistrationForm extends ContentPanel
         adjustFieldsSizes();
     }
 
+    protected void updateDirtyCheck()
+    {
+        updateDirtyCheckAfterChange(formPanel.isDirtyForSavePoint());
+    }
+
+    protected void updateDirtyCheckAfterChange(boolean isDirty)
+    {
+        String message = messageProvider.getMessage(Dict.BUTTON_SAVE);
+        if (isDirty)
+        {
+            message = message + "*";
+        }
+        saveButton.setText(message);
+    }
+
     protected void resetFieldsAfterSave()
     {
         resetPanel();
+        updateDirtyCheckAfterSave();
+    }
+
+    protected void updateDirtyCheckAfterSave()
+    {
+        formPanel.setSavePoint();
+        updateDirtyCheckAfterChange(false);
     }
 
     protected void resetPanel()
     {
         formPanel.reset();
+        updateDirtyCheckAfterReset();
+    }
+
+    protected void updateDirtyCheckAfterReset()
+    {
+        updateDirtyCheckAfterChange(false);
+    }
+
+    protected void revertPanel()
+    {
+        updateDirtyCheckAfterRevert();
+    }
+
+    protected void updateDirtyCheckAfterRevert()
+    {
+        formPanel.resetToSavePoint();
+        updateDirtyCheckAfterChange(false);
     }
 
     public void adjustFieldsSizes()
@@ -164,9 +214,9 @@ public abstract class AbstractRegistrationForm extends ContentPanel
         }
     }
 
-    protected ClickableFormPanel createFormPanel(final IMessageProvider messageProvider)
+    private FormPanelWithSavePoint createFormPanel()
     {
-        final ClickableFormPanel panel = new ClickableFormPanel();
+        final FormPanelWithSavePoint panel = new FormPanelWithSavePoint();
         panel.addClickListener(new InfoBoxResetListener(infoBox));
         panel.setHeaderVisible(false);
         panel.setBodyBorder(false);
@@ -174,6 +224,15 @@ public abstract class AbstractRegistrationForm extends ContentPanel
         panel.setLabelWidth(labelWidth);
         panel.setFieldWidth(fieldWidth);
         panel.setButtonAlign(HorizontalAlignment.RIGHT);
+        panel.addDirtyChangeListener(new Listener<DirtyChangeEvent>()
+            {
+                @Override
+                public void handleEvent(DirtyChangeEvent e)
+                {
+                    updateDirtyCheckAfterChange(e.isDirtyForSavePoint());
+                }
+            });
+
         saveButton = new Button(messageProvider.getMessage(Dict.BUTTON_SAVE));
         saveButton.setStyleAttribute("marginRight", "20px");
         saveButton.setId(getId() + SAVE_BUTTON);
@@ -193,7 +252,9 @@ public abstract class AbstractRegistrationForm extends ContentPanel
                     }
                 }
             });
+        addSaveButtonConfirmationListener();
         resetButton = new Button(messageProvider.getMessage(Dict.BUTTON_RESET));
+        resetButton.setVisible(false);
         resetButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
 
@@ -207,7 +268,25 @@ public abstract class AbstractRegistrationForm extends ContentPanel
                     resetPanel();
                 }
             });
+
+        revertButton = new Button(messageProvider.getMessage(Dict.BUTTON_REVERT));
+        revertButton.setVisible(false);
+        revertButton.addSelectionListener(new SelectionListener<ButtonEvent>()
+            {
+
+                //
+                // SelectionListener
+                //
+
+                @Override
+                public final void componentSelected(final ButtonEvent ce)
+                {
+                    revertPanel();
+                }
+            });
+
         panel.addButton(resetButton);
+        panel.addButton(revertButton);
         panel.addButton(saveButton);
         return panel;
     }
@@ -217,6 +296,40 @@ public abstract class AbstractRegistrationForm extends ContentPanel
         saveButton.setEnabled(enabled);
     }
 
+    protected void setResetButtonVisible(boolean visible)
+    {
+        resetButton.setVisible(visible);
+    }
+
+    protected void setRevertButtonVisible(boolean visible)
+    {
+        revertButton.setVisible(visible);
+    }
+
+    protected void addSaveButtonConfirmationListener()
+    {
+        saveButton.addListener(Events.BeforeSelect, new Listener<BaseEvent>()
+            {
+                @Override
+                public void handleEvent(BaseEvent be)
+                {
+                    if (formPanel.isValid() && formPanel.isDirtyForSavePoint() == false)
+                    {
+                        be.setCancelled(true);
+                        new ConfirmationDialog("Save Confirmation",
+                                "You haven't made any changes. Do you really want to save the form ?")
+                            {
+                                @Override
+                                protected void onYes()
+                                {
+                                    saveButton.fireEvent(Events.Select);
+                                }
+                            }.show();
+                    }
+                }
+            });
+    }
+
     /**
      * Submits a valid form.
      * <p>
@@ -351,4 +464,10 @@ public abstract class AbstractRegistrationForm extends ContentPanel
                 messageProvider.getMessage(entityKindDictKey), identifiable.getCode());
     }
 
+    @Override
+    public boolean shouldAskForCloseConfirmation()
+    {
+        return formPanel.isDirtyForSavePoint();
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CustomImportForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CustomImportForm.java
index 2f60a9fce8b56c245196d01714a49e99c3804404..48642c01355560d66e259090738601217a5f2dce 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CustomImportForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/CustomImportForm.java
@@ -25,7 +25,6 @@ import com.extjs.gxt.ui.client.widget.form.FileUploadField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.FormPanelListener;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.file.BasicFileFieldManager;
 
 /**
@@ -53,7 +52,7 @@ public class CustomImportForm extends AbstractRegistrationForm
             String customImportCode)
     {
         super(viewContext, id);
-
+        setResetButtonVisible(true);
         this.sessionKey = id + "-" + customImportCode;
         this.customImportCode = customImportCode;
         this.viewContext = viewContext;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetUploadForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetUploadForm.java
index 08f57b44428e72c0681691110eb02a2ed6f2fb9d..0bc4843c231c9ca9f6f588ecd514f43b8aec837a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetUploadForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetUploadForm.java
@@ -97,6 +97,7 @@ public class DataSetUploadForm extends AbstractRegistrationForm
             String sampleIdentifierOrNull)
     {
         super(viewContext, createSimpleId(sampleIdentifierOrNull));
+        setResetButtonVisible(true);
         cifexURL = viewContext.getModel().getApplicationInfo().getCifexURL();
         cifexRecipient = viewContext.getModel().getApplicationInfo().getCifexRecipient();
         saveButton.setText(viewContext.getMessage(Dict.BUTTON_UPLOAD_DATA_VIA_CIFEX));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ChosenEntitySetter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ChosenEntitySetter.java
index bba7ff22de096cf2e338e8f55b53300a60b006e4..cf427ff70ef5d931b844d40a14b85f89808db09d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ChosenEntitySetter.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ChosenEntitySetter.java
@@ -37,6 +37,7 @@ public abstract class ChosenEntitySetter<T> extends TriggerField<String> impleme
         setWidth(TEXT_CHOOSER_FIELD_WIDTH);
         setTriggerStyle("x-form-trigger-generate");
         setHideTrigger(false);
+        setFireChangeEventOnSetValue(true);
     }
 
     public void addChosenEntityListener(IChosenEntitiesListener<T> listener)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MultilineVarcharField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MultilineVarcharField.java
index e3fc678a4746ffe56eb18aed7c5a0776cc1fd389..a16cf57e30a8465594405e743af80525692dc041 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MultilineVarcharField.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MultilineVarcharField.java
@@ -49,6 +49,7 @@ public class MultilineVarcharField extends TextArea
         this.setFieldLabel(label);
         this.setValidateOnBlur(true);
         this.setAutoValidate(true);
+        this.setFireChangeEventOnSetValue(true);
         FieldUtil.setMandatoryFlag(this, mandatory);
         setHeightInLines(lines);
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/AttachmentFileUploadField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/AttachmentFileUploadField.java
index 6f28cace8fa39a4889412da366583d38a538f799..a2280fa6e0e159403dca4dc6e9a2dd61843c4925 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/AttachmentFileUploadField.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/AttachmentFileUploadField.java
@@ -41,6 +41,7 @@ public class AttachmentFileUploadField extends FileUploadField
     public AttachmentFileUploadField(final IMessageProvider messageProvider)
     {
         super();
+        setFireChangeEventOnSetValue(true);
         this.fileSet = new AttachmentsFileSet(messageProvider, this);
     }
 
@@ -48,7 +49,7 @@ public class AttachmentFileUploadField extends FileUploadField
     {
         return fileSet;
     }
-    
+
     public void addFieldsTo(FormPanel form, String sessionKey, IMessageProvider messageProvider)
     {
         FileUploadField fileUploadField = fileSet.getFileUploadField();
@@ -58,7 +59,7 @@ public class AttachmentFileUploadField extends FileUploadField
         form.add(fileSet.getDescriptionField());
         form.add(fileSet.getTitleField());
     }
-    
+
     public NewAttachment tryExtractAttachment()
     {
         if (StringUtils.isBlank(getFilePathValue()))
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/BasicFileFieldManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/BasicFileFieldManager.java
index 28a3dd13075915d8a6078cc61d1ce16ddc227bc1..4d3412a5ea40e098c33b52bf76041ece9ffe6fe3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/BasicFileFieldManager.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/file/BasicFileFieldManager.java
@@ -35,7 +35,7 @@ public class BasicFileFieldManager extends FileFieldManager<FileUploadField>
     @Override
     protected FileUploadField createFileUploadField()
     {
-        return new FileUploadField()
+        FileUploadField field = new FileUploadField()
             {
                 @Override
                 public void setEnabled(boolean enabled)
@@ -46,6 +46,8 @@ public class BasicFileFieldManager extends FileFieldManager<FileUploadField>
                     setReadOnly(!enabled);
                 }
             };
+        field.setFireChangeEventOnSetValue(true);
+        return field;
     }
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/AbstractProjectEditRegisterForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/AbstractProjectEditRegisterForm.java
index bf4821753cc420e0f44b3fc02a8915d6ea400334..311aa9755633f69afd50e0fa4e528f5a88fb0f52 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/AbstractProjectEditRegisterForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/AbstractProjectEditRegisterForm.java
@@ -146,6 +146,7 @@ abstract class AbstractProjectEditRegisterForm extends AbstractRegistrationForm
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectEditForm.java
index b4574cc94a92107e403b15603893cb85d34dde25..eb3bf270383cda342e2effd91d8717764801c45c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectEditForm.java
@@ -51,6 +51,7 @@ public class ProjectEditForm extends AbstractProjectEditRegisterForm
     protected ProjectEditForm(IViewContext<ICommonClientServiceAsync> viewContext, TechId projectId)
     {
         super(viewContext, projectId);
+        setRevertButtonVisible(true);
         this.projectId = projectId;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectRegistrationForm.java
index 74f3f07cd28f164348f137026de3320786ad2380..ec83f045e73124df1480fe6b92b93a3bccbad00f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectRegistrationForm.java
@@ -33,6 +33,7 @@ public class ProjectRegistrationForm extends AbstractProjectEditRegisterForm
     protected ProjectRegistrationForm(IViewContext<ICommonClientServiceAsync> viewContext)
     {
         super(viewContext);
+        setResetButtonVisible(true);
     }
 
     public static DatabaseModificationAwareComponent create(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeRegistrationForm.java
index 825f3373e361b728651f98733b187c1cc9310a80..ee434d48e78317ab41d8b855448d2870227c5d38 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeRegistrationForm.java
@@ -85,6 +85,7 @@ public final class PropertyTypeRegistrationForm extends AbstractRegistrationForm
     private PropertyTypeRegistrationForm(final IViewContext<ICommonClientServiceAsync> viewContext)
     {
         super(viewContext, ID, DEFAULT_LABEL_WIDTH + 20, DEFAULT_FIELD_WIDTH);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
 
         this.propertyTypeCodeField = createPropertyTypeCodeField();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/AbstractScriptEditRegisterForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/AbstractScriptEditRegisterForm.java
index c9d50d9e8dc823e0d1e39639f32b850d6ee68a24..805bb60b3d3a70faa557cff6b35cb83492d725dd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/AbstractScriptEditRegisterForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/AbstractScriptEditRegisterForm.java
@@ -208,6 +208,7 @@ abstract public class AbstractScriptEditRegisterForm extends AbstractRegistratio
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptEditForm.java
index c64845ddd074306861c7f94a32d5e89f562bfbe3..cda5e0a075fbae2505543490c0eb2d0d6bac85a9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptEditForm.java
@@ -42,6 +42,7 @@ public class ScriptEditForm extends AbstractScriptEditRegisterForm
     protected ScriptEditForm(IViewContext<ICommonClientServiceAsync> viewContext, TechId scriptId)
     {
         super(viewContext, scriptId, null, null);
+        setRevertButtonVisible(true);
         this.scriptId = scriptId;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptRegistrationForm.java
index e4a86c1957a9769de03fe7fbf12480aa671858d6..2d93d1d5857885901af4e12eeb79c96283333b82 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/script/ScriptRegistrationForm.java
@@ -41,6 +41,7 @@ public class ScriptRegistrationForm extends AbstractScriptEditRegisterForm
             ScriptTypeSelectionWidget scriptTypeChooser, EntityKind entityKindOrNull)
     {
         super(viewContext, scriptTypeChooser, entityKindOrNull);
+        setResetButtonVisible(true);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyRegistrationForm.java
index ecf3c843a1c9d97c6ce544bcabf25b843e3e35f8..6d55e033bc24162ae3a90f4ea0db5dd9b616d5d6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/vocabulary/VocabularyRegistrationForm.java
@@ -50,6 +50,7 @@ public final class VocabularyRegistrationForm extends AbstractRegistrationForm
     public VocabularyRegistrationForm(final IViewContext<ICommonClientServiceAsync> viewContext)
     {
         super(viewContext, ID);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
         termsSessionKey = ID + "_terms";
         this.vocabularyRegistrationFieldSet =
@@ -114,6 +115,7 @@ public final class VocabularyRegistrationForm extends AbstractRegistrationForm
     private void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ClickableFormPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ClickableFormPanel.java
index 9b0ae6d02a08a590302150dee8288a4fbaca27fc..db32cdd7acf48547b1199d0bfe4cb79e3f1b1e4d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ClickableFormPanel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/ClickableFormPanel.java
@@ -26,7 +26,7 @@ import com.google.gwt.event.dom.client.ClickHandler;
  * 
  * @author Christian Ribeaud
  */
-public final class ClickableFormPanel extends FormPanel
+public class ClickableFormPanel extends FormPanel
 {
 
     public final void addClickListener(final ClickHandler handler)
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 70d5f0cb8eab759b3350cd9a86c34d46fb25f34a..3e44d64e49b4e49fbc69607863e7b7a1aec6b9f0 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
@@ -34,8 +34,10 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ActionCont
 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.ComponentWithCloseConfirmationUtil;
 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.IComponentWithCloseConfirmation;
 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;
@@ -50,7 +52,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
  * @author Izabela Adamczyk
  */
 abstract public class EntityRegistrationPanel<T extends ModelData, S extends DropDownList<T, ?>>
-        extends ContentPanel implements IDatabaseModificationObserver
+        extends ContentPanel implements IDatabaseModificationObserver,
+        IComponentWithCloseConfirmation
 {
     private final S entityTypeSelection;
 
@@ -107,15 +110,14 @@ abstract public class EntityRegistrationPanel<T extends ModelData, S extends Dro
     private void onSelectionChanged(final T entityTypeModel)
     {
         final EntityType entityType = entityTypeModel.get(ModelDataPropertyNames.OBJECT);
-        if (registrationWidget == null)
-
+        if (registrationWidget == null || shouldAskForCloseConfirmation() == false)
         {
             showRegistrationForm(entityType);
             previousSelection.update(entityTypeModel);
         } else
         {
-            new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE), viewContext
-                    .getMessage(Dict.CONFIRM_CLOSE_MSG))
+            new ConfirmationDialog(viewContext.getMessage(Dict.CONFIRM_TITLE),
+                    viewContext.getMessage(Dict.CONFIRM_CLOSE_MSG))
                 {
                     @Override
                     protected void onYes()
@@ -141,8 +143,9 @@ abstract public class EntityRegistrationPanel<T extends ModelData, S extends Dro
     {
         removeAll();
         final IClientPlugin<EntityType, IIdAndCodeHolder> clientPlugin =
-                viewContext.getClientPluginFactoryProvider().getClientPluginFactory(entityKind,
-                        entityType).createClientPlugin(entityKind);
+                viewContext.getClientPluginFactoryProvider()
+                        .getClientPluginFactory(entityKind, entityType)
+                        .createClientPlugin(entityKind);
         registrationWidget =
                 clientPlugin.createRegistrationForEntityType(entityType, actionContext);
         add(registrationWidget.get());
@@ -187,4 +190,11 @@ abstract public class EntityRegistrationPanel<T extends ModelData, S extends Dro
     {
         createCompositeDatabaseModificationObserver().update(observedModifications);
     }
+
+    @Override
+    public boolean shouldAskForCloseConfirmation()
+    {
+        return ComponentWithCloseConfirmationUtil.shouldAskForCloseConfirmation(registrationWidget
+                .get());
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/FormPanelWithSavePoint.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/FormPanelWithSavePoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb2d05ecd71fcdf80e434383bee30ae2796fd917
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/FormPanelWithSavePoint.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2012 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.widget;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.event.BaseEvent;
+import com.extjs.gxt.ui.client.event.ContainerEvent;
+import com.extjs.gxt.ui.client.event.Events;
+import com.extjs.gxt.ui.client.event.FieldEvent;
+import com.extjs.gxt.ui.client.event.Listener;
+import com.extjs.gxt.ui.client.util.Util;
+import com.extjs.gxt.ui.client.widget.Component;
+import com.extjs.gxt.ui.client.widget.Container;
+import com.extjs.gxt.ui.client.widget.form.Field;
+
+/**
+ * @author pkupczyk
+ */
+
+@SuppressWarnings(
+    { "rawtypes", "unchecked" })
+public class FormPanelWithSavePoint extends ClickableFormPanel
+{
+
+    private List<Listener<DirtyChangeEvent>> dirtyChangeListeners =
+            new ArrayList<Listener<DirtyChangeEvent>>();
+
+    private Set<Field<?>> dirtyCheckIgnoredFields = new HashSet<Field<?>>();
+
+    private Map<String, Object> dirtyCheckSavePointValues = new HashMap<String, Object>();
+
+    public FormPanelWithSavePoint()
+    {
+        addListener(Events.Add, new Listener<ContainerEvent>()
+            {
+                @Override
+                public void handleEvent(ContainerEvent e)
+                {
+                    addDirtyCheckField(e.getItem());
+                }
+            });
+    }
+
+    public void setSavePoint()
+    {
+        dirtyCheckSavePointValues.clear();
+        for (Field field : getFields())
+        {
+            setSavePointValue(field);
+        }
+    }
+
+    @Override
+    public void reset()
+    {
+        super.reset();
+        setSavePoint();
+    }
+
+    public void resetToSavePoint()
+    {
+        for (Field field : getFields())
+        {
+            field.setValue(getSavePointValue(field));
+        }
+    }
+
+    private void setSavePointValue(Field<?> field)
+    {
+        dirtyCheckSavePointValues.put(field.getId(), field.getValue());
+    }
+
+    private Object getSavePointValue(Field<?> field)
+    {
+        if (dirtyCheckSavePointValues.containsKey(field.getId()))
+        {
+            return dirtyCheckSavePointValues.get(field.getId());
+        } else
+        {
+            return field.getOriginalValue();
+        }
+    }
+
+    private void addDirtyCheckField(Component component)
+    {
+        if (component instanceof Field<?>)
+        {
+            Field<?> field = (Field<?>) component;
+            field.addListener(Events.Change, new Listener<FieldEvent>()
+                {
+                    @Override
+                    public void handleEvent(FieldEvent e)
+                    {
+                        DirtyChangeEvent dirtyChangedEvent =
+                                new DirtyChangeEvent(FormPanelWithSavePoint.this);
+
+                        for (Listener<DirtyChangeEvent> dirtyChangeListener : dirtyChangeListeners)
+                        {
+                            dirtyChangeListener.handleEvent(dirtyChangedEvent);
+                        }
+                    }
+                });
+        } else if (component instanceof Container<?>)
+        {
+            Container<Component> container = (Container<Component>) component;
+            for (Component item : container.getItems())
+            {
+                addDirtyCheckField(item);
+            }
+        }
+    }
+
+    public void addDirtyCheckIgnoredField(Field<?> field)
+    {
+        dirtyCheckIgnoredFields.add(field);
+    }
+
+    public boolean isDirtyForSavePoint()
+    {
+        for (Field<?> field : getFields())
+        {
+            if (dirtyCheckIgnoredFields.contains(field) == false)
+            {
+                Object currentValue = field.getValue();
+                Object savePointValue = getSavePointValue(field);
+
+                if (currentValue instanceof String && Util.isEmptyString((String) currentValue))
+                {
+                    currentValue = null;
+                }
+                if (savePointValue instanceof String && Util.isEmptyString((String) savePointValue))
+                {
+                    savePointValue = null;
+                }
+                if (Util.equalWithNull(currentValue, savePointValue) == false)
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public void addDirtyChangeListener(Listener<DirtyChangeEvent> listener)
+    {
+        dirtyChangeListeners.add(listener);
+    }
+
+    public class DirtyChangeEvent extends BaseEvent
+    {
+
+        private boolean isDirtyForSavePoint;
+
+        public DirtyChangeEvent(FormPanelWithSavePoint form)
+        {
+            super(form);
+            this.isDirtyForSavePoint = form.isDirtyForSavePoint();
+        }
+
+        public boolean isDirtyForSavePoint()
+        {
+            return isDirtyForSavePoint;
+        }
+
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Space.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Space.java
index 593ea28b16a377fa1e6333feb9aeedeede638da1..58469092a504ec62b15fdf11f07f4ab7862c9307 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Space.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Space.java
@@ -87,7 +87,13 @@ public final class Space extends CodeWithRegistration<Space> implements IIdHolde
     @Override
     public String toString()
     {
-        return getInstance().getCode() + "/" + getCode();
+        if (getInstance() != null)
+        {
+            return getInstance().getCode() + "/" + getCode();
+        } else
+        {
+            return "/" + getCode();
+        }
     }
 
     @Override
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 3c44f5bdacda15c58e17db15adf31a2252f8f0e8..d7b197f7592e8aab88570d5e57df8e20862d866d 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
@@ -109,8 +109,8 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType
     // ID generation
     // ---------------------------------------------------------------------------------------------
     /**
-     * Creates unique id based on {@link #createSimpleId(IIdAndCodeHolder, EntityKind)} and application
-     * specific ID prefix.
+     * Creates unique id based on {@link #createSimpleId(IIdAndCodeHolder, EntityKind)} and
+     * application specific ID prefix.
      */
     public static final String createId(IIdAndCodeHolder identifiable, EntityKind entityKind)
     {
@@ -129,7 +129,8 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType
     /**
      * Creates unique form id for given entity.
      */
-    protected static final String createSimpleId(IIdAndCodeHolder identifiable, EntityKind entityKind)
+    protected static final String createSimpleId(IIdAndCodeHolder identifiable,
+            EntityKind entityKind)
     {
         return createSimpleId(TechId.create(identifiable), entityKind);
     }
@@ -175,8 +176,8 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType
     private final void createCommonFormFields()
     {
         propertiesEditor =
-                createPropertiesEditor(createId(techIdOrNull, entityKind), viewContext
-                        .getCommonViewContext());
+                createPropertiesEditor(createId(techIdOrNull, entityKind),
+                        viewContext.getCommonViewContext());
         codeField =
                 new CodeFieldWithGenerator(viewContext, viewContext.getMessage(Dict.CODE),
                         getGeneratedCodePrefix(), isAutoGenerateCode());
@@ -190,6 +191,11 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType
             // (contained sample code has ':' inside and it is invalid)
             codeField.disable();
         }
+
+        if (isAutoGenerateCode())
+        {
+            formPanel.addDirtyCheckIgnoredField(codeField);
+        }
     }
 
     /**
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java
index a8a97c29b4db32cd23e0344f8e33c807adc4b34f..7d6012942980f092afda3e505cbbdd35197388c3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/GeneralImportForm.java
@@ -74,7 +74,7 @@ public class GeneralImportForm extends AbstractRegistrationForm
             String id, String sessionKey)
     {
         super(genericViewContext, id);
-
+        setResetButtonVisible(true);
         this.sessionKey = sessionKey;
         this.genericViewContext = genericViewContext;
         setScrollMode(Scroll.AUTO);
@@ -154,6 +154,7 @@ public class GeneralImportForm extends AbstractRegistrationForm
         {
             attachmentField.reset();
         }
+        updateDirtyCheckAfterSave();
     }
 
     private final void addOnlyFormFields(boolean forceAddEmailField)
@@ -192,6 +193,7 @@ public class GeneralImportForm extends AbstractRegistrationForm
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetBatchUpdateForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetBatchUpdateForm.java
index 77a9510c9fadfc578b1b39b7e107a4264c7b324b..7785cdfc56d8ca9b7b8c80daae73e01d3c4d9eaa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetBatchUpdateForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetBatchUpdateForm.java
@@ -75,6 +75,7 @@ public final class GenericDataSetBatchUpdateForm extends AbstractRegistrationFor
             final DataSetType dataSetType)
     {
         super(viewContext.getCommonViewContext(), ID);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
         this.dataSetType = dataSetType;
         fileFieldsManager =
@@ -92,6 +93,7 @@ public final class GenericDataSetBatchUpdateForm extends AbstractRegistrationFor
         {
             attachmentField.reset();
         }
+        updateDirtyCheckAfterSave();
     }
 
     private final void addFormFields()
@@ -127,6 +129,7 @@ public final class GenericDataSetBatchUpdateForm extends AbstractRegistrationFor
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
index 1dd565dfab7d9f6744e2f07eb9b895258a9913f4..de50cac187a5feda512ab1c89dc7771be62b125c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java
@@ -21,6 +21,7 @@ import static ch.systemsx.cisd.openbis.generic.client.web.client.application.fra
 import java.util.ArrayList;
 import java.util.List;
 
+import com.extjs.gxt.ui.client.event.BaseEvent;
 import com.extjs.gxt.ui.client.event.Events;
 import com.extjs.gxt.ui.client.event.FieldEvent;
 import com.extjs.gxt.ui.client.event.Listener;
@@ -108,6 +109,7 @@ public final class GenericDataSetEditForm extends
             IIdAndCodeHolder identifiable)
     {
         super(viewContext, identifiable, EntityKind.DATA_SET);
+        setRevertButtonVisible(true);
         simpleId = createSimpleId(identifiable, EntityKind.DATA_SET);
     }
 
@@ -305,7 +307,14 @@ public final class GenericDataSetEditForm extends
                 DefaultResultSetConfig.createFetchAll();
         viewContext.getCommonService().listDataSetRelationships(techIdOrNull,
                 DataSetRelationshipRole.CHILD, config, new ListParentsCallback(viewContext));
-        builder.loadDataInBackground();
+        builder.loadDataInBackground(new Listener<BaseEvent>()
+            {
+                @Override
+                public void handleEvent(BaseEvent be)
+                {
+                    updateDirtyCheck();
+                }
+            });
     }
 
     private void updateFieldsVisibility()
@@ -380,6 +389,7 @@ public final class GenericDataSetEditForm extends
                     result.getResultSet().getList().extractOriginalObjects();
             List<ExternalData> dataSets = extractDataSets(rows);
             parentsArea.setDataSets(dataSets);
+            updateDirtyCheck();
             if (parentsArea.isVisible())
             {
                 parentsArea.setEnabled(true);
@@ -392,7 +402,7 @@ public final class GenericDataSetEditForm extends
 
         void updateOriginalValues(DataSetUpdateResult result);
 
-        void loadDataInBackground();
+        void loadDataInBackground(Listener<BaseEvent> listener);
 
         void fillUpdates(DataSetUpdates result);
 
@@ -454,7 +464,7 @@ public final class GenericDataSetEditForm extends
         }
 
         @Override
-        public void loadDataInBackground()
+        public void loadDataInBackground(Listener<BaseEvent> listener)
         {
             // nothing to do
         }
@@ -513,7 +523,7 @@ public final class GenericDataSetEditForm extends
         }
 
         @Override
-        public void loadDataInBackground()
+        public void loadDataInBackground(Listener<BaseEvent> listener)
         {
             // not best performance but the same solution that is done for experiments
             // only codes are needed but we extract 'full' object
@@ -521,16 +531,20 @@ public final class GenericDataSetEditForm extends
                     DefaultResultSetConfig.createFetchAll();
             viewContext.getCommonService().listDataSetRelationships(techIdOrNull,
                     DataSetRelationshipRole.CONTAINER, config,
-                    new ListContainedDataSetsCallback(viewContext));
+                    new ListContainedDataSetsCallback(viewContext, listener));
         }
 
         private class ListContainedDataSetsCallback extends
                 AbstractAsyncCallback<TypedTableResultSet<ExternalData>>
         {
 
-            public ListContainedDataSetsCallback(IViewContext<?> viewContext)
+            private Listener<BaseEvent> listener;
+
+            public ListContainedDataSetsCallback(IViewContext<?> viewContext,
+                    Listener<BaseEvent> listener)
             {
                 super(viewContext);
+                this.listener = listener;
             }
 
             @Override
@@ -539,6 +553,7 @@ public final class GenericDataSetEditForm extends
                 List<TableModelRowWithObject<ExternalData>> rows =
                         result.getResultSet().getList().extractOriginalObjects();
                 containedArea.setDataSets(extractDataSets(rows));
+                listener.handleEvent(null);
                 if (containedArea.isVisible())
                 {
                     containedArea.setEnabled(true);
@@ -596,7 +611,7 @@ public final class GenericDataSetEditForm extends
         }
 
         @Override
-        public void loadDataInBackground()
+        public void loadDataInBackground(Listener<BaseEvent> listener)
         {
             // nothing to do
         }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractExperimentBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractExperimentBatchRegistrationForm.java
index 5bf2249f9af36fa0b30366f9bf5c1f0d016a097d..4c8e57b1951434234c3c24f1a0767bb5d458907c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractExperimentBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractExperimentBatchRegistrationForm.java
@@ -118,6 +118,7 @@ public abstract class AbstractExperimentBatchRegistrationForm extends AbstractRe
         {
             attachmentField.reset();
         }
+        updateDirtyCheckAfterSave();
     }
 
     private static String createId(String sessionKey)
@@ -170,6 +171,7 @@ public abstract class AbstractExperimentBatchRegistrationForm extends AbstractRe
     private void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java
index f3c90db2c9da77cead1269d9e195775fbf327f01..b92fcec069e0839847eada5c8e7969d1bc9c190e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java
@@ -135,6 +135,7 @@ abstract public class AbstractGenericExperimentRegisterEditForm extends
     private void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
@@ -240,8 +241,8 @@ abstract public class AbstractGenericExperimentRegisterEditForm extends
                     if (typeSelection.tryGetSelectedSampleType() != null)
                     {
                         WindowUtils.openWindow(UrlParamsHelper.createTemplateURL(EntityKind.SAMPLE,
-                                typeSelection.tryGetSelected(), autoGenerate.getValue(), false, false, 
-                                BatchOperationKind.REGISTRATION));
+                                typeSelection.tryGetSelected(), autoGenerate.getValue(), false,
+                                false, BatchOperationKind.REGISTRATION));
                     } else
                     {
                         MessageBox.alert("Sample type not selected.",
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchRegistrationForm.java
index 3f4db895e77d8fd9366ef782821199894214f4a8..e9245991e75b8f781848e2f87d5c2d1eb0b7bff0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchRegistrationForm.java
@@ -32,10 +32,10 @@ public final class GenericExperimentBatchRegistrationForm extends
     private static final String SESSION_KEY = "experiment-batch-registration";
 
     public GenericExperimentBatchRegistrationForm(
-            final IViewContext<IGenericClientServiceAsync> viewContext,
-            final ExperimentType type)
+            final IViewContext<IGenericClientServiceAsync> viewContext, final ExperimentType type)
     {
         super(viewContext, type, BatchOperationKind.REGISTRATION, SESSION_KEY);
+        setResetButtonVisible(true);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchUpdateForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchUpdateForm.java
index a725679983ebc9ff464969d66e165bf62e17733a..de27d3a866bf6e4c8e504b486e62a423ccca14b3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchUpdateForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentBatchUpdateForm.java
@@ -22,8 +22,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType;
 import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class GenericExperimentBatchUpdateForm extends AbstractExperimentBatchRegistrationForm
@@ -31,10 +29,10 @@ public class GenericExperimentBatchUpdateForm extends AbstractExperimentBatchReg
     private static final String SESSION_KEY = "experiment-batch-update";
 
     public GenericExperimentBatchUpdateForm(
-            final IViewContext<IGenericClientServiceAsync> viewContext,
-            final ExperimentType type)
+            final IViewContext<IGenericClientServiceAsync> viewContext, final ExperimentType type)
     {
         super(viewContext, type, BatchOperationKind.UPDATE, SESSION_KEY);
+        setResetButtonVisible(true);
     }
 
     @Override
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 cf74efb6458c051e849dfb98e7a4799726c9e9aa..639e1d5f33e809f8cb57e5d5f85e519567ed6623 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
@@ -54,6 +54,7 @@ public final class GenericExperimentEditForm extends AbstractGenericExperimentRe
             IIdAndCodeHolder identifiable)
     {
         super(viewContext, new ActionContext(), identifiable);
+        setRevertButtonVisible(true);
     }
 
     private void loadSamplesInBackground()
@@ -78,6 +79,7 @@ public final class GenericExperimentEditForm extends AbstractGenericExperimentRe
         {
             samplesArea.setSamples(result.getResultSet().getList().extractOriginalObjects());
             samplesArea.setEnabled(true);
+            updateDirtyCheck();
         }
     }
 
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 33882be89f8fd0c800c1f829ae2cbd334405929c..0d0dde340f6d5592d069a5ec7e496cb228aed30f 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
@@ -47,6 +47,7 @@ public final class GenericExperimentRegistrationForm extends
             final ActionContext context, final ExperimentType experimentType)
     {
         super(viewContext, context);
+        setResetButtonVisible(true);
         this.experimentType = experimentType;
     }
 
@@ -60,6 +61,7 @@ public final class GenericExperimentRegistrationForm extends
             importSamplesField.reset();
         }
         samplesArea.reset();
+        updateDirtyCheckAfterSave();
     }
 
     private final String createExperimentIdentifier()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/AbstractMaterialBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/AbstractMaterialBatchRegistrationForm.java
index 89b5b7d7dac14abd9eb294765f62c5f4de4302df..06767a5fa6940e1e6ed43910a861f88b179812d2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/AbstractMaterialBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/AbstractMaterialBatchRegistrationForm.java
@@ -49,8 +49,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistrationForm
@@ -63,11 +61,11 @@ abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistratio
     {
         return GenericConstants.ID_PREFIX + sessionKey;
     }
-    
+
     protected final MaterialType materialType;
-    
+
     protected final IViewContext<IGenericClientServiceAsync> viewContext;
-    
+
     private final BasicFileFieldManager fileFieldsManager;
 
     private final BatchOperationKind batchOperationKind;
@@ -85,7 +83,7 @@ abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistratio
         fileFieldsManager.setMandatory();
         addUploadFeatures(sessionKey);
     }
-    
+
     /**
      * Adds additional fields to the form panel. File upload field will be added automatically after
      * specific fields.
@@ -93,13 +91,12 @@ abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistratio
     protected void addSpecificFormFields(FormPanel form)
     {
     }
-    
+
     /**
      * Perform registration on the service
      */
     protected abstract void save();
 
-
     @Override
     protected void submitValidForm()
     {
@@ -111,7 +108,7 @@ abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistratio
         super.onRender(target, index);
         addFormFields();
     }
-    
+
     private final void addFormFields()
     {
         addSpecificFormFields(formPanel);
@@ -154,10 +151,11 @@ abstract class AbstractMaterialBatchRegistrationForm extends AbstractRegistratio
             });
         return result;
     }
-    
+
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchRegistrationForm.java
index c1fc2403dfc5ab6cc53dc75b87ef08a99fb98799..ee39eed66f33c0ab171265fa5a8f5a2919210eb5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchRegistrationForm.java
@@ -48,6 +48,7 @@ public final class GenericMaterialBatchRegistrationForm extends
             final MaterialType materialType)
     {
         super(viewContext, PREFIX, BatchOperationKind.REGISTRATION, materialType);
+        setResetButtonVisible(true);
         updateExistingCheckbox =
                 new CheckBoxField(viewContext.getMessage(Dict.UPDATE_EXISTING_ENTITIES_LABEL),
                         false);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchUpdateForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchUpdateForm.java
index 4146b4a9cc767752b026a3b5abe8b6e162280c48..f238ca76ab90c8e4ce6c2be1d7964cd87f3b40c0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchUpdateForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialBatchUpdateForm.java
@@ -26,26 +26,26 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 public class GenericMaterialBatchUpdateForm extends AbstractMaterialBatchRegistrationForm
 {
     private static final String PREFIX = "material-batch-update";
-    
+
     private static final String SESSION_KEY = PREFIX;
 
     private final CheckBoxField ignoreUnregisteredMaterialsCheckBox;
-    
-    public GenericMaterialBatchUpdateForm(final IViewContext<IGenericClientServiceAsync> viewContext,
+
+    public GenericMaterialBatchUpdateForm(
+            final IViewContext<IGenericClientServiceAsync> viewContext,
             final MaterialType materialType)
     {
         super(viewContext, PREFIX, BatchOperationKind.UPDATE, materialType);
+        setResetButtonVisible(true);
         ignoreUnregisteredMaterialsCheckBox =
                 new CheckBoxField(viewContext.getMessage(Dict.IGNORE_UNREGISTERED_MATERIALS), false);
     }
-    
+
     @Override
     protected void addSpecificFormFields(FormPanel form)
     {
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 c4a482d3fe2c3a8f4c1777577c3cf7e00b1a6c82..22e62919ebd699afe84f34be219e6712de4671e9 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
@@ -58,6 +58,7 @@ public final class GenericMaterialEditForm extends
             IIdAndCodeHolder identifiable, boolean editMode)
     {
         super(viewContext, identifiable, EntityKind.MATERIAL);
+        setRevertButtonVisible(true);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
index 2f980442348ee0222ae858694d98a0493c16f1fe..ebdc4c47dd2a3b3b55fe977f141d4d232286980b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
@@ -168,6 +168,7 @@ abstract public class AbstractGenericSampleRegisterEditForm extends
     private void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractSampleBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractSampleBatchRegistrationForm.java
index edb82df3675ac51c2a297fe9e496b76f7a0976e2..003b0fa721ef1ba7537352ed8b260681e0c909a5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractSampleBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractSampleBatchRegistrationForm.java
@@ -99,6 +99,7 @@ public abstract class AbstractSampleBatchRegistrationForm extends AbstractRegist
         {
             attachmentField.reset();
         }
+        updateDirtyCheckAfterSave();
     }
 
     private static String createId(String sessionKey)
@@ -133,6 +134,7 @@ public abstract class AbstractSampleBatchRegistrationForm extends AbstractRegist
     private void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java
index 9f0be1a3f60f5bbe150103bcdcf95e539dda2291..e21448616f7a8025349b13f611c11a93a8fee120 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java
@@ -68,6 +68,7 @@ public final class GenericSampleBatchRegistrationForm extends AbstractSampleBatc
             final IViewContext<IGenericClientServiceAsync> viewContext, final SampleType sampleType)
     {
         super(viewContext.getCommonViewContext(), SESSION_KEY);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
         this.sampleType = sampleType;
         generateCodesCheckbox =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchUpdateForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchUpdateForm.java
index 7d2aa8e69acd04293b9a1eaaca0a3e744b998d66..0ccc6f34eb70b961815633183d5e139f95570f48 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchUpdateForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchUpdateForm.java
@@ -79,6 +79,7 @@ public final class GenericSampleBatchUpdateForm extends AbstractRegistrationForm
             final SampleType sampleType)
     {
         super(viewContext.getCommonViewContext(), ID);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
         this.sampleType = sampleType;
         fileFieldsManager =
@@ -105,6 +106,7 @@ public final class GenericSampleBatchUpdateForm extends AbstractRegistrationForm
         {
             attachmentField.reset();
         }
+        updateDirtyCheckAfterSave();
     }
 
     private final void addFormFields()
@@ -144,6 +146,7 @@ public final class GenericSampleBatchUpdateForm extends AbstractRegistrationForm
     void redefineSaveListeners()
     {
         saveButton.removeAllListeners();
+        addSaveButtonConfirmationListener();
         saveButton.addSelectionListener(new SelectionListener<ButtonEvent>()
             {
                 @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 cf225e2f00fbbafd09dde55f16204588942cc37b..f0ee17240b98f4c95a390a3e97f2a29a4ce701a4 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
@@ -58,6 +58,7 @@ public final class GenericSampleEditForm extends AbstractGenericSampleRegisterEd
             IIdAndCodeHolder identifiable)
     {
         super(viewContext, new ActionContext(), identifiable);
+        setRevertButtonVisible(true);
     }
 
     @Override
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 a9965237e953ff7bceab16923ed82d0cf6c053a7..490f37d86a06a3e2e5dfb1f45dd1ea7f8846413f 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
@@ -41,6 +41,7 @@ public final class GenericSampleRegistrationForm extends AbstractGenericSampleRe
             final SampleType sampleType, ActionContext actionContext)
     {
         super(viewContext, actionContext);
+        setResetButtonVisible(true);
         this.sampleType = sampleType;
     }
 
@@ -49,6 +50,7 @@ public final class GenericSampleRegistrationForm extends AbstractGenericSampleRe
     {
         codeField.reset();
         attachmentsManager.resetAttachmentFieldSetsInPanel(formPanel);
+        updateDirtyCheckAfterSave();
     }
 
     // public only for tests
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index b886ea43758ef4e521f0313bb57309cdeb6aaf27..74acd04f5eb8d2fc340cb870e8c8afdc9068be6e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -144,6 +144,7 @@ var common = {
   button_choose: "Choose",
   button_cancel: "Cancel",
   button_reset: "Clear",
+  button_revert: "Revert",
   button_submit: "Submit",
   button_refresh: "Refresh",
   button_show: "Show",
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/sample/LibrarySampleBatchRegistrationForm.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/sample/LibrarySampleBatchRegistrationForm.java
index d30cbb5617cc455656ed4980f311b9f0aa3996b0..d5915f04d9b4b251663b829d91e46eb6df44f5bb 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/sample/LibrarySampleBatchRegistrationForm.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/client/web/client/application/sample/LibrarySampleBatchRegistrationForm.java
@@ -98,6 +98,7 @@ public final class LibrarySampleBatchRegistrationForm extends AbstractSampleBatc
             final IViewContext<IScreeningClientServiceAsync> viewContext)
     {
         super(viewContext.getCommonViewContext(), SESSION_KEY);
+        setResetButtonVisible(true);
         this.viewContext = viewContext;
         experimentChooser =
                 ExperimentChooserField.create(viewContext.getMessage(Dict.EXPERIMENT), true, null,