diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/console/Assignment.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/console/Assignment.java
index 1d566327cdc2e437f3c7c71b959909802f989898..cd5e19c3e59835b15b810afbac284729907d9ee1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/console/Assignment.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/console/Assignment.java
@@ -18,10 +18,9 @@ package ch.systemsx.cisd.openbis.generic.client.console;
 
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 class Assignment implements ICommand
@@ -29,7 +28,8 @@ class Assignment implements ICommand
 
     private static final String MANDATORY = "mandatory";
 
-    public void execute(ICommonServer server, String sessionToken, ScriptContext context, String argument)
+    public void execute(ICommonServer server, String sessionToken, ScriptContext context,
+            String argument)
     {
         String[] arguments = argument.split(" ");
         String[] entityKindAndType = arguments[0].split(":");
@@ -46,8 +46,10 @@ class Assignment implements ICommand
             }
             isMandatory = true;
         }
-        server.assignPropertyType(sessionToken, entityKind, propertyTypeCode, entityTypeCode,
-                isMandatory, null, null, 0L);
+        NewETPTAssignment newAssignment =
+                new NewETPTAssignment(entityKind, propertyTypeCode, entityTypeCode, isMandatory,
+                        null, null, 0L, false, null);
+        server.assignPropertyType(sessionToken, newAssignment);
 
     }
 
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 395b056cbb0e5809f76111ce4b711d52fc80a392..3ac8948e7e87ce581729ae5dda8c9bb17368ddd1 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
@@ -65,6 +65,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -76,6 +77,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Null;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -86,6 +88,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -118,6 +121,18 @@ public interface ICommonClientService extends IClientService
     public ResultSet<Space> listGroups(DefaultResultSetConfig<String, Space> criteria)
             throws UserFailureException;
 
+    /**
+     * Returns a list of all scripts.
+     */
+    public ResultSet<Script> listScripts(DefaultResultSetConfig<String, Script> criteria)
+            throws UserFailureException;
+
+    /**
+     * Like {@link #prepareExportSamples(TableExportCriteria)}, but for scripts.
+     */
+    public String prepareExportScripts(final TableExportCriteria<Script> criteria)
+            throws UserFailureException;
+
     /**
      * Like {@link #prepareExportSamples(TableExportCriteria)}, but for groups.
      */
@@ -130,6 +145,11 @@ public interface ICommonClientService extends IClientService
     public void registerGroup(String groupCode, String descriptionOrNull)
             throws UserFailureException;
 
+    /**
+     * Updates script.
+     */
+    public void updateScript(final IScriptUpdates updates) throws UserFailureException;
+
     /**
      * Updates group.
      */
@@ -436,9 +456,7 @@ public interface ICommonClientService extends IClientService
     /**
      * Assigns property type to entity type.
      */
-    public String assignPropertyType(EntityKind entityKind, String propertyTypeCode,
-            String entityTypeCode, boolean isMandatory, String defaultValue, String section,
-            Long previousETPTOrdinal) throws UserFailureException;
+    public String assignPropertyType(NewETPTAssignment assignment) throws UserFailureException;
 
     /**
      * Unassigns property type to entity type.
@@ -596,6 +614,9 @@ public interface ICommonClientService extends IClientService
     /** Deletes the specified groups. */
     public void deleteGroups(List<TechId> groupIds, String reason) throws UserFailureException;
 
+    /** Deletes the specified scripts. */
+    public void deleteScripts(List<TechId> scriptIds) throws UserFailureException;
+
     /** Deletes the specified vocabularies. */
     public void deleteVocabularies(List<TechId> vocabualryIds, String reason)
             throws UserFailureException;
@@ -729,14 +750,14 @@ public interface ICommonClientService extends IClientService
     public TypedTableResultSet<Null> listReport(
             IResultSetConfig<String, TableModelRowWithObject<Null>> resultSetConfig)
             throws UserFailureException;
-    
+
     /**
      * Like {@link #prepareExportSamples(TableExportCriteria)}, but for TableModelRow.
      */
     public String prepareExportReport(
             TableExportCriteria<TableModelRowWithObject<Null>> exportCriteria)
             throws UserFailureException;
-    
+
     /**
      * Uses the specified datastore service to schedule processing of the specified datasets.
      */
@@ -785,6 +806,11 @@ public interface ICommonClientService extends IClientService
     public void registerAuthorizationGroup(NewAuthorizationGroup newAuthorizationGroup)
             throws UserFailureException;
 
+    /**
+     * Creates a new script.
+     */
+    public void registerScript(Script newScript) throws UserFailureException;
+
     /**
      * Returns a list persons belonging to given authorization group.
      */
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 c4f74c6b4efda23a0faabd2474ddfe5105793f6a..e4e5188a5cc20acbf03e4744c88232e7e47acefa 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
@@ -67,6 +67,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -78,6 +79,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Null;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -88,6 +90,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -109,6 +112,14 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listGroups(DefaultResultSetConfig<String, Space> criteria,
             final AsyncCallback<ResultSet<Space>> asyncCallback);
 
+    /** @see ICommonClientService#listScripts(DefaultResultSetConfig) */
+    public void listScripts(DefaultResultSetConfig<String, Script> criteria,
+            final AsyncCallback<ResultSet<Script>> asyncCallback);
+
+    /** @see ICommonClientService#prepareExportScripts(TableExportCriteria) */
+    public void prepareExportScripts(TableExportCriteria<Script> exportCriteria,
+            AsyncCallback<String> callback);
+
     /** @see ICommonClientService#prepareExportGroups(TableExportCriteria) */
     public void prepareExportGroups(TableExportCriteria<Space> exportCriteria,
             AsyncCallback<String> callback);
@@ -117,6 +128,12 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void registerGroup(String groupCode, String descriptionOrNull,
             AsyncCallback<Void> callback);
 
+    /** @see ICommonClientService#registerScript(Script) */
+    public void registerScript(Script newScript, AsyncCallback<Void> callback);
+
+    /** @see ICommonClientService#updateScript(IScriptUpdates) */
+    public void updateScript(final IScriptUpdates updates, final AsyncCallback<Void> asyncCallback);
+
     /** @see ICommonClientService#updateGroup(ISpaceUpdates) */
     public void updateGroup(final ISpaceUpdates updates, final AsyncCallback<Void> asyncCallback);
 
@@ -366,12 +383,9 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listDataTypes(final AsyncCallback<List<DataType>> asyncCallback);
 
     /**
-     * @see ICommonClientService#assignPropertyType(EntityKind, String, String, boolean, String,
-     *      String, Long)
+     * @see ICommonClientService#assignPropertyType(NewETPTAssignment assignment)
      */
-    public void assignPropertyType(EntityKind entityKind, String propertyTypeCode,
-            String entityTypeCode, boolean isMandatory, String defaultValue, String section,
-            Long previousETPTOrdinal, AsyncCallback<String> process);
+    public void assignPropertyType(NewETPTAssignment assignment, AsyncCallback<String> process);
 
     /**
      * @see ICommonClientService#updatePropertyTypeAssignment(EntityKind, String, String, boolean,
@@ -511,6 +525,9 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     /** @see ICommonClientService#deleteGroups(List, String) */
     public void deleteGroups(List<TechId> groupIds, String value, AsyncCallback<Void> asyncCallback);
 
+    /** @see ICommonClientService#deleteScripts(List) */
+    public void deleteScripts(List<TechId> scriptIds, AsyncCallback<Void> asyncCallback);
+
     /** @see ICommonClientService#deleteVocabularies(List, String) */
     public void deleteVocabularies(List<TechId> vocabularyIds, String value,
             AsyncCallback<Void> asyncCallback);
@@ -633,13 +650,14 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
      */
     public void listReport(IResultSetConfig<String, TableModelRowWithObject<Null>> resultSetConfig,
             AsyncCallback<TypedTableResultSet<Null>> callback);
-    
+
     /**
      * @see ICommonClientService#prepareExportReport(TableExportCriteria)
      */
-    public void prepareExportReport(TableExportCriteria<TableModelRowWithObject<Null>> exportCriteria,
+    public void prepareExportReport(
+            TableExportCriteria<TableModelRowWithObject<Null>> exportCriteria,
             AsyncCallback<String> callback);
-    
+
     /**
      * @see ICommonClientService#processDatasets(DatastoreServiceDescription,
      *      DisplayedOrSelectedDatasetCriteria)
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 8bb21b59b0d22edaa21fc1d5859a586c36807566..9a577828a74c563b17465ed29789153801938a90 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
@@ -31,6 +31,8 @@ public abstract class Dict
 
     public static final String ADD_GROUP_TITLE = "add_group_title";
 
+    public static final String ADD_SCRIPT_TITLE = "add_script_title";
+
     protected Dict()
     {
         // Can not be instantiated.
@@ -330,6 +332,7 @@ public abstract class Dict
 
     public static final String IS_DYNAMIC = "is_dynamic";
 
+    // TODO 2010-10-14, IA: would PYTHON_SCRIPT be more self explanatory?? Will it always be python?
     public static final String SCRIPT = "script";
 
     public static final String PROPERTY_TYPE = "property_type";
@@ -360,6 +363,8 @@ public abstract class Dict
 
     public static final String MANDATORY = "mandatory";
 
+    public static final String DYNAMIC = "dynamic";
+
     public static final String SECTION_TOOLTIP = "section_tooltip";
 
     public static final String DEFAULT_VALUE = "default_value";
@@ -747,6 +752,8 @@ public abstract class Dict
 
     public static final String TITLE_CHOOSE_MATERIAL = "title_choose_material";
 
+    public static final String TITLE_CHOOSE_SCRIPT = "title_choose_script";
+
     public static final String CHOOSE_ANY_MATERIAL = "choose_any_material";
 
     public static final String INCORRECT_MATERIAL_SYNTAX = "incorrect_material_syntax";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DisplayTypeIDGenerator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DisplayTypeIDGenerator.java
index f37ba146836f404ba890e49d4c1bf15ac8c553bc..8b6982b872d135602b193e05f894539b515eb4ab 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DisplayTypeIDGenerator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/DisplayTypeIDGenerator.java
@@ -60,6 +60,8 @@ public enum DisplayTypeIDGenerator implements IDisplayTypeIDGenerator
 
     GROUPS_BROWSER_GRID("group-browser-grid"),
 
+    SCRIPTS_BROWSER_GRID("script-browser-grid"),
+
     ROLE_ASSIGNMENT_BROWSER_GRID("role-assignment-browser-grid"),
 
     PROPERTY_TYPE_BROWSER_GRID("property-type-browser-grid"),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddGroupDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddGroupDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb78a6a39785f9a6bb24561e91dbbdeac2b0eeab
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddGroupDialog.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import com.extjs.gxt.ui.client.widget.Window;
+import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.DescriptionField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
+
+/**
+ * {@link Window} containing group registration form.
+ * 
+ * @author Franz-Josef Elmer
+ * @author Izabela Adamczyk
+ */
+public class AddGroupDialog extends AbstractRegistrationDialog
+{
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private final TextField<String> codeField;
+
+    private final DescriptionField descriptionField;
+
+    public AddGroupDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final IDelegatedAction postRegistrationCallback)
+    {
+        super(viewContext, viewContext.getMessage(Dict.ADD_GROUP_TITLE),
+                postRegistrationCallback);
+        this.viewContext = viewContext;
+        this.codeField = createCodeField(viewContext);
+        addField(codeField);
+
+        this.descriptionField = createDescriptionField(viewContext);
+        addField(descriptionField);
+    }
+
+    @Override
+    protected void register(AsyncCallback<Void> registrationCallback)
+    {
+        viewContext.getService().registerGroup(codeField.getValue(), descriptionField.getValue(),
+                registrationCallback);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddScriptDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddScriptDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..d78528930cd0df408cc8b970686fd9e8a0196d6a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/AddScriptDialog.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import com.extjs.gxt.ui.client.widget.Window;
+import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.DescriptionField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField;
+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.AbstractRegistrationDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+
+/**
+ * {@link Window} containing script registration form.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class AddScriptDialog extends AbstractRegistrationDialog
+{
+    private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+    private final TextField<String> nameField;
+
+    private final DescriptionField descriptionField;
+
+    private final MultilineVarcharField scriptField;
+
+    public AddScriptDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final IDelegatedAction postRegistrationCallback)
+    {
+        super(viewContext, viewContext.getMessage(Dict.ADD_SCRIPT_TITLE), postRegistrationCallback);
+        this.viewContext = viewContext;
+        this.nameField = new VarcharField(viewContext.getMessage(Dict.NAME), true);
+        addField(nameField);
+
+        this.descriptionField = createDescriptionField(viewContext);
+        addField(descriptionField);
+
+        this.scriptField = new MultilineVarcharField(viewContext.getMessage(Dict.SCRIPT), true, 20);
+        addField(scriptField);
+    }
+
+    @Override
+    protected void register(AsyncCallback<Void> registrationCallback)
+    {
+        Script newScript = new Script();
+        newScript.setDescription(descriptionField.getValue());
+        newScript.setName(nameField.getValue());
+        newScript.setScript(scriptField.getValue());
+        viewContext.getService().registerScript(newScript, registrationCallback);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ScriptGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ScriptGrid.java
new file mode 100644
index 0000000000000000000000000000000000000000..643f1b4441360eed7d461f950e2cad0efc608230
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/ScriptGrid.java
@@ -0,0 +1,266 @@
+/*
+ * 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.ui;
+
+import java.util.List;
+
+import com.extjs.gxt.ui.client.event.ButtonEvent;
+import com.extjs.gxt.ui.client.event.SelectionListener;
+import com.extjs.gxt.ui.client.widget.Dialog;
+import com.extjs.gxt.ui.client.widget.Window;
+import com.extjs.gxt.ui.client.widget.button.Button;
+import com.extjs.gxt.ui.client.widget.form.TextField;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.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.framework.DisplayTypeIDGenerator;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.specific.ScriptColDefKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.DescriptionField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.VarcharField;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.AbstractSimpleBrowserGrid;
+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.ui.grid.IBrowserGridActionInvoker;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractDataListDeletionConfirmationDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractRegistrationDialog;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
+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.client.web.client.dto.TableExportCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+
+/**
+ * Grid displaying scripts.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ScriptGrid extends AbstractSimpleBrowserGrid<Script>
+{
+    // browser consists of the grid and the paging toolbar
+    public static final String BROWSER_ID = GenericConstants.ID_PREFIX + "script-browser";
+
+    public static final String GRID_ID = BROWSER_ID + "_grid";
+
+    public static final String ADD_BUTTON_ID = BROWSER_ID + "_add-button";
+
+    public static final String DELETE_BUTTON_ID = BROWSER_ID + "_delete-button";
+
+    public static final String EDIT_BUTTON_ID = BROWSER_ID + "-edit-button";
+
+    private final IDelegatedAction postRegistrationCallback;
+
+    public static DisposableEntityChooser<Script> create(
+            final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        final ScriptGrid grid = new ScriptGrid(viewContext);
+        grid.extendBottomToolbar();
+        return grid.asDisposableWithoutToolbar();
+    }
+
+    private ScriptGrid(IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        super(viewContext, BROWSER_ID, GRID_ID, DisplayTypeIDGenerator.SCRIPTS_BROWSER_GRID);
+        postRegistrationCallback = createRefreshGridAction();
+    }
+
+    private void extendBottomToolbar()
+    {
+        addEntityOperationsLabel();
+
+        final Button addScriptButton =
+                new Button(viewContext.getMessage(Dict.BUTTON_ADD,
+                        viewContext.getMessage(Dict.SCRIPT)), new SelectionListener<ButtonEvent>()
+                    {
+                        @Override
+                        public void componentSelected(ButtonEvent ce)
+                        {
+                            AddScriptDialog dialog =
+                                    new AddScriptDialog(viewContext, createRefreshGridAction());
+                            dialog.show();
+                        }
+                    });
+        addScriptButton.setId(ADD_BUTTON_ID);
+        addButton(addScriptButton);
+
+        Button editButton =
+                createSelectedItemButton(viewContext.getMessage(Dict.BUTTON_EDIT),
+                        new ISelectedEntityInvoker<BaseEntityModel<Script>>()
+                            {
+                                public void invoke(BaseEntityModel<Script> selectedItem,
+                                        boolean keyPressed)
+                                {
+                                    Script script = selectedItem.getBaseObject();
+                                    createEditDialog(script).show();
+                                }
+                            });
+        editButton.setId(EDIT_BUTTON_ID);
+        addButton(editButton);
+
+        Button deleteButton =
+                createSelectedItemsButton(viewContext.getMessage(Dict.BUTTON_DELETE),
+                        new AbstractCreateDialogListener()
+                            {
+                                @Override
+                                protected Dialog createDialog(List<Script> scripts,
+                                        IBrowserGridActionInvoker invoker)
+                                {
+                                    return new ScriptListDeletionConfirmationDialog(viewContext,
+                                            scripts, createDeletionCallback(invoker));
+                                }
+                            });
+        addButton(deleteButton);
+        allowMultipleSelection(); // we allow deletion of multiple projects
+
+        addEntityOperationsSeparator();
+    }
+
+    private Window createEditDialog(final Script script)
+    {
+        final String name = script.getName();
+        final String description = script.getDescription();
+        final String title =
+                viewContext.getMessage(Dict.EDIT_TITLE, viewContext.getMessage(Dict.SCRIPT), name);
+
+        return new AbstractRegistrationDialog(viewContext, title, postRegistrationCallback)
+            {
+                private final TextField<String> nameField;
+
+                private final DescriptionField descriptionField;
+
+                private final MultilineVarcharField scriptField;
+
+                {
+                    this.nameField = new VarcharField(viewContext.getMessage(Dict.NAME), true);
+                    this.nameField.setValue(StringEscapeUtils.unescapeHtml(script.getName()));
+                    addField(nameField);
+
+                    descriptionField = createDescriptionField(viewContext);
+                    descriptionField.setValue(StringEscapeUtils.unescapeHtml(description));
+                    addField(descriptionField);
+
+                    this.scriptField =
+                            new MultilineVarcharField(viewContext.getMessage(Dict.SCRIPT), true, 20);
+                    this.scriptField.setValue(StringEscapeUtils.unescapeHtml(script.getScript()));
+                    addField(scriptField);
+                }
+
+                @Override
+                protected void register(AsyncCallback<Void> registrationCallback)
+                {
+                    script.setDescription(descriptionField.getValue());
+                    script.setScript(scriptField.getValue());
+                    script.setName(nameField.getValue());
+
+                    viewContext.getService().updateScript(script, registrationCallback);
+                }
+            };
+    }
+
+    @Override
+    protected IColumnDefinitionKind<Script>[] getStaticColumnsDefinition()
+    {
+        return ScriptColDefKind.values();
+    }
+
+    @Override
+    protected ColumnDefsAndConfigs<Script> createColumnsDefinition()
+    {
+        ColumnDefsAndConfigs<Script> schema = super.createColumnsDefinition();
+        schema.setGridCellRendererFor(ScriptColDefKind.DESCRIPTION.id(),
+                createMultilineStringCellRenderer());
+        schema.setGridCellRendererFor(ScriptColDefKind.SCRIPT.id(),
+                createMultilineStringCellRenderer());
+        return schema;
+    }
+
+    @Override
+    protected void listEntities(DefaultResultSetConfig<String, Script> resultSetConfig,
+            AbstractAsyncCallback<ResultSet<Script>> callback)
+    {
+        viewContext.getService().listScripts(resultSetConfig, callback);
+    }
+
+    @Override
+    protected void prepareExportEntities(TableExportCriteria<Script> exportCriteria,
+            AbstractAsyncCallback<String> callback)
+    {
+        viewContext.getService().prepareExportScripts(exportCriteria, callback);
+    }
+
+    @Override
+    protected List<IColumnDefinition<Script>> getInitialFilters()
+    {
+        return asColumnFilters(new ScriptColDefKind[]
+            { ScriptColDefKind.NAME });
+    }
+
+    @Override
+    protected void showEntityViewer(final Script script, boolean editMode, boolean inBackground)
+    {
+        assert false : "not implemented";
+    }
+
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return new DatabaseModificationKind[]
+            { DatabaseModificationKind.createOrDelete(ObjectKind.SCRIPT),
+                    DatabaseModificationKind.edit(ObjectKind.SCRIPT) };
+    }
+
+    private static final class ScriptListDeletionConfirmationDialog extends
+            AbstractDataListDeletionConfirmationDialog<Script>
+    {
+
+        private final IViewContext<ICommonClientServiceAsync> viewContext;
+
+        private final AbstractAsyncCallback<Void> callback;
+
+        public ScriptListDeletionConfirmationDialog(
+                IViewContext<ICommonClientServiceAsync> viewContext, List<Script> data,
+                AbstractAsyncCallback<Void> callback)
+        {
+            super(viewContext, data);
+            this.viewContext = viewContext;
+            this.callback = callback;
+        }
+
+        @Override
+        protected void executeConfirmedAction()
+        {
+            viewContext.getCommonService().deleteScripts(TechId.createList(data), callback);
+        }
+
+        @Override
+        protected String getEntityName()
+        {
+            return messageProvider.getMessage(Dict.SCRIPT);
+        }
+
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddGroupDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddGroupDialog.java
index 6a45994c3d6e4f27eb4d7b736cbffebaba1720e0..731213a6e1449b3ba85faf2acf9d4e1f2b0bfe69 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddGroupDialog.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/amc/AddGroupDialog.java
@@ -44,8 +44,7 @@ public class AddGroupDialog extends AbstractRegistrationDialog
     public AddGroupDialog(final IViewContext<ICommonClientServiceAsync> viewContext,
             final IDelegatedAction postRegistrationCallback)
     {
-        super(viewContext, viewContext.getMessage(Dict.ADD_GROUP_TITLE),
-                postRegistrationCallback);
+        super(viewContext, viewContext.getMessage(Dict.ADD_GROUP_TITLE), postRegistrationCallback);
         this.viewContext = viewContext;
         this.codeField = createCodeField(viewContext);
         addField(codeField);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/ScriptColDefKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/ScriptColDefKind.java
new file mode 100644
index 0000000000000000000000000000000000000000..eae09ca494165af9573b392e30d2adb124251c3c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/ScriptColDefKind.java
@@ -0,0 +1,91 @@
+/*
+ * 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.ui.columns.specific;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.AbstractColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+
+/**
+ * @author Izabela Adamczyk
+ */
+public enum ScriptColDefKind implements IColumnDefinitionKind<Script>
+{
+    NAME(new AbstractColumnDefinitionKind<Script>(Dict.NAME)
+        {
+            @Override
+            public String tryGetValue(Script entity)
+            {
+                return entity.getName();
+            }
+        }),
+
+    DESCRIPTION(new AbstractColumnDefinitionKind<Script>(Dict.DESCRIPTION)
+        {
+            @Override
+            public String tryGetValue(Script entity)
+            {
+                return entity.getDescription();
+            }
+        }),
+
+    SCRIPT(new AbstractColumnDefinitionKind<Script>(Dict.SCRIPT)
+        {
+            @Override
+            public String tryGetValue(Script entity)
+            {
+                return entity.getScript();
+            }
+        }),
+
+    REGISTRATOR(new AbstractColumnDefinitionKind<Script>(Dict.REGISTRATOR)
+        {
+            @Override
+            public String tryGetValue(Script entity)
+            {
+                return renderRegistrator(entity);
+            }
+        }),
+
+    REGISTRATION_DATE(new AbstractColumnDefinitionKind<Script>(Dict.REGISTRATION_DATE,
+            AbstractColumnDefinitionKind.DATE_COLUMN_WIDTH, false)
+        {
+            @Override
+            public String tryGetValue(Script entity)
+            {
+                return renderRegistrationDate(entity);
+            }
+        });
+
+    private final AbstractColumnDefinitionKind<Script> columnDefinitionKind;
+
+    private ScriptColDefKind(AbstractColumnDefinitionKind<Script> columnDefinitionKind)
+    {
+        this.columnDefinitionKind = columnDefinitionKind;
+    }
+
+    public String id()
+    {
+        return name();
+    }
+
+    public AbstractColumnDefinitionKind<Script> getDescriptor()
+    {
+        return columnDefinitionKind;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ScriptChooserField.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ScriptChooserField.java
new file mode 100644
index 0000000000000000000000000000000000000000..3035b3da94be5284f8c28c4c6de32300e7f42aae
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/ScriptChooserField.java
@@ -0,0 +1,82 @@
+/*
+ * 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.field;
+
+import com.extjs.gxt.ui.client.event.ComponentEvent;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync;
+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.ui.ScriptGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableEntityChooser;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+
+/**
+ * A field for selecting a script.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class ScriptChooserField extends ChosenEntitySetter<Script>
+{
+
+    public static ScriptChooserField create(final String labelField, final boolean mandatory,
+            String initialValueOrNull, final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        final ScriptChooserField field =
+                new ScriptChooserField(mandatory, initialValueOrNull, viewContext)
+                    {
+                        @Override
+                        protected void onTriggerClick(ComponentEvent ce)
+                        {
+                            super.onTriggerClick(ce);
+                            browseScripts(viewContext, this);
+                        }
+                    };
+
+        field.setFieldLabel(labelField);
+        return field;
+    }
+
+    private static void browseScripts(final IViewContext<ICommonClientServiceAsync> viewContext,
+            final ChosenEntitySetter<Script> chosenScriptField)
+    {
+        DisposableEntityChooser<Script> scriptBrowser = ScriptGrid.create(viewContext);
+        String title = viewContext.getMessage(Dict.TITLE_CHOOSE_SCRIPT);
+        new EntityChooserDialog<Script>(scriptBrowser, chosenScriptField, title, viewContext)
+                .show();
+    }
+
+    @Override
+    public String renderEntity(Script script)
+    {
+        return script.getName();
+    }
+
+    private ScriptChooserField(boolean mandatory, String initialValueOrNull,
+            IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        FieldUtil.setMandatoryFlag(this, mandatory);
+        setValidateOnBlur(true);
+        setAutoValidate(true);
+        if (initialValueOrNull != null)
+        {
+            setValue(initialValueOrNull);
+        }
+    }
+
+}
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 b0f8465218d3e67683b706d9879de0db795169a2..9e2c48636cababeadd29c6a58cecd3835de83f13 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
@@ -51,6 +51,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.Da
 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.CheckBoxField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.PropertyFieldFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.ScriptChooserField;
 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.SampleTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.DropDownList;
@@ -61,6 +62,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKin
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 
 /**
@@ -115,6 +117,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
 
     private CheckBox mandatoryCheckbox;
 
+    private CheckBox dynamicCheckbox;
+
     private SectionSelectionWidget sectionSelectionWidget;
 
     private EntityTypePropertyTypeSelectionWidget etptSelectionWidget;
@@ -129,6 +133,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
 
     private final EntityKind entityKind;
 
+    private final ScriptChooserField scriptChooser;
+
     public static DatabaseModificationAwareComponent create(
             final IViewContext<ICommonClientServiceAsync> viewContext, EntityKind entityKind)
     {
@@ -147,6 +153,17 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         setScrollMode(Scroll.AUTO);
         add(infoBox = createInfoBox());
         add(formPanel = createFormPanel());
+        scriptChooser = createScriptChooserField(viewContext);
+    }
+
+    private static ScriptChooserField createScriptChooserField(
+            final IViewContext<ICommonClientServiceAsync> viewContext)
+    {
+        ScriptChooserField field =
+                ScriptChooserField.create(viewContext.getMessage(Dict.SCRIPT), true, null,
+                        viewContext);
+        FieldUtil.setVisibility(false, field);
+        return field;
     }
 
     public static final String createId(EntityKind entityKind)
@@ -251,6 +268,36 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         return result;
     }
 
+    private CheckBox getDynamicCheckbox()
+    {
+        if (dynamicCheckbox == null)
+        {
+            dynamicCheckbox = new CheckBoxField(viewContext.getMessage(Dict.DYNAMIC), false);
+            dynamicCheckbox.setValue(false);
+            dynamicCheckbox.addListener(Events.Change, new Listener<BaseEvent>()
+                {
+                    public void handleEvent(BaseEvent be)
+                    {
+                        updateVisibilityOfDynamicRelatedFields(dynamicCheckbox.getValue());
+                    }
+                });
+        }
+        return dynamicCheckbox;
+    }
+
+    private void updateVisibilityOfDynamicRelatedFields(Boolean isDynmic)
+    {
+        FieldUtil.setVisibility(isDynmic, scriptChooser);
+        if (defaultValueField != null)
+        {
+            FieldUtil.setVisibility(isDynmic == false, defaultValueField.get());
+        }
+        if (mandatoryCheckbox != null)
+        {
+            FieldUtil.setVisibility(isDynmic == false, mandatoryCheckbox);
+        }
+    }
+
     private CheckBox getMandatoryCheckbox()
     {
         if (mandatoryCheckbox == null)
@@ -260,6 +307,7 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
             mandatoryCheckbox.setFireChangeEventOnSetValue(false);
             mandatoryCheckbox.setValue(false);
             mandatoryCheckbox.addListener(Events.Change, new InfoBoxResetListener(infoBox));
+            FieldUtil.setVisibility(dynamicCheckbox.getValue() == false, mandatoryCheckbox);
         }
         return mandatoryCheckbox;
     }
@@ -351,6 +399,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         DropDownList<?, ?> typeSelectionWidget = getTypeSelectionWidget();
         formPanel.add(propertyTypeWidget);
         formPanel.add(typeSelectionWidget);
+        formPanel.add(getDynamicCheckbox());
+        formPanel.add(scriptChooser);
         formPanel.add(getMandatoryCheckbox());
         updatePropertyTypeRelatedFields();
 
@@ -403,12 +453,13 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                     createChildId(DEFAULT_VALUE_ID_PART
                             + GWTUtils.escapeToFormId(propertyType.getSimpleCode()));
             DatabaseModificationAwareField<?> fieldHolder =
-                    PropertyFieldFactory.createField(propertyType, false, viewContext
-                            .getMessage(Dict.DEFAULT_VALUE), fieldId, null, viewContext);
-            GWTUtils.setToolTip(fieldHolder.get(), viewContext
-                    .getMessage(Dict.DEFAULT_VALUE_TOOLTIP));
+                    PropertyFieldFactory.createField(propertyType, false,
+                            viewContext.getMessage(Dict.DEFAULT_VALUE), fieldId, null, viewContext);
+            GWTUtils.setToolTip(fieldHolder.get(),
+                    viewContext.getMessage(Dict.DEFAULT_VALUE_TOOLTIP));
             defaultValueField = fieldHolder;
             defaultValueField.get().show();
+            FieldUtil.setVisibility(dynamicCheckbox.getValue() == false, defaultValueField.get());
             formPanel.add(defaultValueField.get());
         }
         updateEntityTypePropertyTypeRelatedFields();
@@ -483,10 +534,15 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
     {
         if (formPanel.isValid())
         {
-            viewContext.getService().assignPropertyType(entityKind,
-                    propertyTypeSelectionWidget.tryGetSelectedPropertyTypeCode(),
-                    getSelectedEntityCode(), getMandatoryCheckbox().getValue(), getDefaultValue(),
-                    getSectionValue(), getPreviousETPTOrdinal(),
+            boolean dynamic = dynamicCheckbox.getValue();
+            String scriptOrNull = scriptChooser != null ? scriptChooser.getValue() : null;
+            NewETPTAssignment newAssignment =
+                    new NewETPTAssignment(entityKind,
+                            propertyTypeSelectionWidget.tryGetSelectedPropertyTypeCode(),
+                            getSelectedEntityCode(), getMandatoryCheckbox().getValue(),
+                            getDefaultValue(), getSectionValue(), getPreviousETPTOrdinal(),
+                            dynamic, scriptOrNull);
+            viewContext.getService().assignPropertyType(newAssignment,
                     new AssignPropertyTypeCallback(viewContext));
         }
     }
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 4a9a0256fe8be467c1495a808c012a5f9ff2d9e8..7d6e0afd9626120a369550e39d03f5d195ea7b02 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
@@ -106,6 +106,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -119,6 +120,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyTyp
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Null;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -130,6 +132,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelColumnHeader;
@@ -293,6 +296,20 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public final void updateScript(final IScriptUpdates updates)
+    {
+        assert updates != null : "Unspecified updates.";
+
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.updateScript(sessionToken, updates);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public final void registerPerson(final String code)
     {
         try
@@ -451,6 +468,11 @@ public final class CommonClientService extends AbstractClientService implements
         return prepareExportEntities(criteria);
     }
 
+    public String prepareExportScripts(TableExportCriteria<Script> criteria)
+    {
+        return prepareExportEntities(criteria);
+    }
+
     public String prepareExportGroups(TableExportCriteria<Space> criteria)
     {
         return prepareExportEntities(criteria);
@@ -598,6 +620,31 @@ public final class CommonClientService extends AbstractClientService implements
             });
     }
 
+    public ResultSet<Script> listScripts(DefaultResultSetConfig<String, Script> criteria)
+    {
+        return listEntities(criteria, new AbstractOriginalDataProviderWithoutHeaders<Script>()
+            {
+                public List<Script> getOriginalData() throws UserFailureException
+                {
+                    return listScripts();
+                }
+            });
+    }
+
+    private List<Script> listScripts()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            final List<Script> scripts = commonServer.listScripts(sessionToken);
+            return scripts;
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     private List<Space> listGroups()
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
@@ -945,16 +992,13 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
-    public String assignPropertyType(final EntityKind entityKind, final String propertyTypeCode,
-            final String entityTypeCode, final boolean isMandatory, final String defaultValue,
-            final String section, final Long previousETPTOrdinal)
+    public String assignPropertyType(NewETPTAssignment assignment)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         try
         {
             final String sessionToken = getSessionToken();
-            return commonServer.assignPropertyType(sessionToken, entityKind, propertyTypeCode,
-                    entityTypeCode, isMandatory, defaultValue, section, previousETPTOrdinal);
+            return commonServer.assignPropertyType(sessionToken, assignment);
         } catch (final UserFailureException e)
         {
             throw UserFailureExceptionTranslator.translate(e);
@@ -1670,6 +1714,19 @@ public final class CommonClientService extends AbstractClientService implements
         }
     }
 
+    public void deleteScripts(List<TechId> scriptIds)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.deleteScripts(sessionToken, scriptIds);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+    }
+
     public void deleteAttachments(TechId holderId, AttachmentHolderKind holderKind,
             List<String> fileNames, String reason)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
@@ -2072,7 +2129,7 @@ public final class CommonClientService extends AbstractClientService implements
     {
         return prepareExportEntities(criteria);
     }
-    
+
     private List<String> extractDatasetCodes(
             DisplayedOrSelectedDatasetCriteria displayedOrSelectedDatasetCriteria)
     {
@@ -2216,6 +2273,19 @@ public final class CommonClientService extends AbstractClientService implements
 
     }
 
+    public void registerScript(Script script)
+    {
+        try
+        {
+            final String sessionToken = getSessionToken();
+            commonServer.registerScript(sessionToken, script);
+        } catch (final UserFailureException e)
+        {
+            throw UserFailureExceptionTranslator.translate(e);
+        }
+
+    }
+
     public List<Person> listPersonsInAuthorizationGroup(TechId group)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
index 922b79e6280148ea0f77e29f5639171742e5d343..c4f929b587c6d42c4904a303b7fbb48b7f39a823 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IPropertyTypeTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IScriptBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyTermBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.MaterialBO;
@@ -58,6 +59,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.PropertyTypeTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.RoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SampleTable;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ScriptBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.VocabularyBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.VocabularyTermBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.datasetlister.DatasetLister;
@@ -94,6 +96,11 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac
         return new GroupBO(getDaoFactory(), session);
     }
 
+    public final IScriptBO createScriptBO(final Session session)
+    {
+        return new ScriptBO(getDaoFactory(), session);
+    }
+
     public final IRoleAssignmentTable createRoleAssignmentTable(final Session session)
     {
         return new RoleAssignmentTable(getDaoFactory(), session);
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 d8cd774a531ea4efbe9904653141f21272787e73..df043e7505b2dc55409bdc187976a7d54fbc2e00 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
@@ -57,6 +57,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IPropertyTypeTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.IScriptBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyTermBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.datasetlister.IDatasetLister;
@@ -98,6 +99,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -114,6 +116,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewMaterial;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
@@ -124,6 +127,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.UpdatedSample;
@@ -156,6 +160,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectUpdatesDTO;
 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.ScriptPE;
 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.SessionContextDTO;
@@ -181,6 +186,7 @@ import ch.systemsx.cisd.openbis.generic.shared.translator.ProjectTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.PropertyTypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.RoleAssignmentTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTypeTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.translator.ScriptTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.TypeTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTermTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTranslator;
@@ -278,6 +284,16 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         groupBO.save();
     }
 
+    public final void updateScript(final String sessionToken, final IScriptUpdates updates)
+    {
+        assert sessionToken != null : "Unspecified session token";
+        assert updates != null : "Unspecified updates";
+
+        final Session session = getSession(sessionToken);
+        final IScriptBO bo = businessObjectFactory.createScriptBO(session);
+        bo.update(updates);
+    }
+
     public final void updateSpace(final String sessionToken, final ISpaceUpdates updates)
     {
         assert sessionToken != null : "Unspecified session token";
@@ -623,22 +639,19 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         HibernateUtils.initialize(vocabularyPE.getTerms());
     }
 
-    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
-            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue, final String section, final Long previousETPTOrdinal)
+    public String assignPropertyType(final String sessionToken, NewETPTAssignment assignment)
     {
         assert sessionToken != null : "Unspecified session token";
         Session session = getSession(sessionToken);
 
         final ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind kind =
-                DtoConverters.convertEntityKind(entityKind);
+                DtoConverters.convertEntityKind(assignment.getEntityKind());
         IEntityTypePropertyTypeBO etptBO =
                 businessObjectFactory.createEntityTypePropertyTypeBO(session, kind);
-        etptBO.createAssignment(propertyTypeCode, entityTypeCode, isMandatory, defaultValue,
-                section, previousETPTOrdinal);
+        etptBO.createAssignment(assignment);
         return String.format("%s property type '%s' successfully assigned to %s type '%s'",
-                isMandatory ? "Mandatory" : "Optional", propertyTypeCode, kind.getLabel(),
-                entityTypeCode);
+                assignment.isMandatory() ? "Mandatory" : "Optional",
+                assignment.getPropertyTypeCode(), kind.getLabel(), assignment.getEntityTypeCode());
     }
 
     public void updatePropertyTypeAssignment(final String sessionToken,
@@ -1129,6 +1142,22 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         }
     }
 
+    public void deleteScripts(String sessionToken, List<TechId> scriptIds)
+    {
+        Session session = getSession(sessionToken);
+        try
+        {
+            IScriptBO scriptBO = businessObjectFactory.createScriptBO(session);
+            for (TechId id : scriptIds)
+            {
+                scriptBO.deleteByTechId(id);
+            }
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
     public void deleteExperimentAttachments(String sessionToken, TechId experimentId,
             List<String> fileNames, String reason)
     {
@@ -1741,6 +1770,20 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         }
     }
 
+    public void registerScript(String sessionToken, Script script)
+    {
+        Session session = getSession(sessionToken);
+        try
+        {
+            IScriptBO bo = businessObjectFactory.createScriptBO(session);
+            bo.define(script);
+            bo.save();
+        } catch (final DataAccessException ex)
+        {
+            throw createUserFailureException(ex);
+        }
+    }
+
     public void deleteAuthorizationGroups(String sessionToken, List<TechId> groupIds, String reason)
     {
         Session session = getSession(sessionToken);
@@ -1767,6 +1810,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return AuthorizationGroupTranslator.translate(persons);
     }
 
+    public List<Script> listScripts(String sessionToken)
+    {
+        checkSession(sessionToken);
+        // FIXME: list only from current database instance
+        final List<ScriptPE> scripts = getDAOFactory().getScriptDAO().listAllEntities();
+        Collections.sort(scripts);
+        return ScriptTranslator.translate(scripts);
+    }
+
     public Date updateAuthorizationGroup(String sessionToken, AuthorizationGroupUpdates updates)
     {
         final Session session = getSession(sessionToken);
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 15c4ad1fa71934b6ecd4e7d383d1c50312436944..e7e18249dde673b45f08845b634963335dae3008 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
@@ -49,6 +49,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Grantee;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -63,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
@@ -72,6 +74,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -140,6 +143,11 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         logTracking(sessionToken, "register_space", "CODE(%s)", groupCode);
     }
 
+    public void updateScript(String sessionToken, IScriptUpdates updates)
+    {
+        logTracking(sessionToken, "update_script", "SCRIPT(%s)", updates.getId());
+    }
+
     public void updateSpace(String sessionToken, ISpaceUpdates updates)
     {
         logTracking(sessionToken, "update_space", "SPACE(%s)", updates);
@@ -312,6 +320,12 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
+    public final List<Script> listScripts(final String sessionToken)
+    {
+        logAccess(sessionToken, "list_scripts");
+        return null;
+    }
+
     public List<FileFormatType> listFileFormatTypes(String sessionToken)
     {
         logAccess(sessionToken, "list_file_format_types");
@@ -325,14 +339,14 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
-    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
-            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue, final String section, final Long previousETPTOrdinal)
+    public String assignPropertyType(final String sessionToken, NewETPTAssignment assignment)
     {
-        final String entityTypeFormat = entityKind.name() + "_TYPE(%S)";
+        final String entityTypeFormat = assignment.getEntityKind().name() + "_TYPE(%S)";
         logTracking(sessionToken, "assign_property_type", " PROPERTY_TYPE(%S) " + entityTypeFormat
-                + " MANDATORY(%S) DEFAULT(%S) SECTION(%S) PREVIOUS_ORDINAL(%S)", propertyTypeCode,
-                entityTypeCode, isMandatory, defaultValue, section, previousETPTOrdinal);
+                + " MANDATORY(%S) DEFAULT(%S) SECTION(%S) PREVIOUS_ORDINAL(%S)",
+                assignment.getPropertyTypeCode(), assignment.getEntityTypeCode(),
+                assignment.isMandatory(), assignment.getDefaultValue(), assignment.getSection(),
+                assignment.getOrdinal());
         return null;
     }
 
@@ -549,6 +563,11 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
                 reason);
     }
 
+    public void deleteScripts(String sessionToken, List<TechId> scriptIds)
+    {
+        logTracking(sessionToken, "delete_scripts", "IDS(%s)", abbreviate(scriptIds));
+    }
+
     public void deleteExperimentAttachments(String sessionToken, TechId experimentId,
             List<String> fileNames, String reason)
     {
@@ -770,6 +789,12 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
 
     }
 
+    public void registerScript(String sessionToken, Script script)
+    {
+        logTracking(sessionToken, "registerScript", "NAME(%s)", script.getName());
+
+    }
+
     public void deleteAuthorizationGroups(String sessionToken, List<TechId> authGroupIds,
             String reason)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
index 530bd52da90aacc18d7a3468ba82849a2c5486d2..54471ef824ab050c294a79a3cdbc31fa1fc35253 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractBusinessObject.java
@@ -46,6 +46,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRelationshipTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRoleAssignmentDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleTypeDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IScriptDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyTermDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources;
@@ -162,6 +163,11 @@ abstract class AbstractBusinessObject implements IDAOFactory
         return daoFactory.getGroupDAO();
     }
 
+    public final IScriptDAO getScriptDAO()
+    {
+        return daoFactory.getScriptDAO();
+    }
+
     public final IPersonDAO getPersonDAO()
     {
         return daoFactory.getPersonDAO();
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
index 97c41c9af1475d9584d24af7a50256be471883ac..600319d25ca6444858f2596b3fee812133fa4372 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
@@ -28,11 +28,13 @@ import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityPropertyTypeDAO;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 
@@ -45,8 +47,8 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         IEntityTypePropertyTypeBO
 {
 
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, EntityTypePropertyTypeBO.class);
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            EntityTypePropertyTypeBO.class);
 
     private EntityKind entityKind;
 
@@ -103,16 +105,18 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         return entityPropertyTypeDAO.countAssignmentValues(entityTypeCode, propertyTypeCode);
     }
 
-    public void createAssignment(String propertyTypeCode, String entityTypeCode,
-            boolean isMandatory, String defaultValue, String section, Long previousETPTOrdinal)
+    public void createAssignment(NewETPTAssignment newAssignment)
     {
-        EntityTypePE entityType = findEntityType(entityTypeCode);
-        PropertyTypePE propertyType = findPropertyType(propertyTypeCode);
+        EntityTypePE entityType = findEntityType(newAssignment.getEntityTypeCode());
+        PropertyTypePE propertyType = findPropertyType(newAssignment.getPropertyTypeCode());
+        ScriptPE scriptOrNull = tryFindScript(newAssignment);
         assignment =
-                createAssignment(isMandatory, section, previousETPTOrdinal, entityType,
-                        propertyType);
+                createAssignment(newAssignment.isMandatory(), newAssignment.getSection(),
+                        newAssignment.getOrdinal(), entityType, propertyType,
+                        newAssignment.isDynamic(), scriptOrNull);
+        String defaultValue = newAssignment.getDefaultValue();
         // fill default property values
-        if (isMandatory)
+        if (newAssignment.isMandatory())
         {
             String errorMsgTemplate =
                     "Cannot create mandatory assignment. "
@@ -128,6 +132,17 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         }
     }
 
+    private ScriptPE tryFindScript(NewETPTAssignment newAssignment)
+    {
+        if (newAssignment.isDynamic() == false)
+        {
+            return null;
+        } else
+        {
+            return getScriptDAO().tryFindByName(newAssignment.getScriptName());
+        }
+    }
+
     private List<Long> getAllEntityIds(EntityTypePE entityType)
     {
         return getEntityPropertyTypeDAO(entityKind).listEntityIds(entityType);
@@ -146,8 +161,8 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
             }
             if (StringUtils.isEmpty(defaultValue))
             {
-                throw new UserFailureException(String.format(errorMsgTemplate, size, entityKind
-                        .getLabel(), createPlural(size), entityType.getCode()));
+                throw new UserFailureException(String.format(errorMsgTemplate, size,
+                        entityKind.getLabel(), createPlural(size), entityType.getCode()));
             }
             PersonPE registrator = findRegistrator();
             String validatedValue =
@@ -219,7 +234,7 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
 
     private EntityTypePropertyTypePE createAssignment(final boolean mandatory,
             final String section, final Long previousETPTOrdinal, final EntityTypePE entityType,
-            final PropertyTypePE propertyType)
+            final PropertyTypePE propertyType, boolean dynamic, ScriptPE scriptOrNull)
     {
         checkAssignmentDoesNotExist(entityType, propertyType);
         // need to shift existing etpts to create space for new one
@@ -234,6 +249,8 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         etpt.setMandatory(mandatory);
         etpt.setSection(section);
         etpt.setOrdinal(currentOrdinal);
+        etpt.setDynamic(dynamic);
+        etpt.setScript(scriptOrNull);
 
         try
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
index 2ff1099aa8925d26d635d9ea3743534b25d73efa..21d3feec2742dbb104f86a65e0ff088e444c7f87 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ICommonBusinessObjectFactory.java
@@ -34,6 +34,8 @@ public interface ICommonBusinessObjectFactory
 
     public IGroupBO createGroupBO(final Session session);
 
+    public IScriptBO createScriptBO(final Session session);
+
     public IRoleAssignmentTable createRoleAssignmentTable(final Session session);
 
     public ISampleTable createSampleTable(final Session session);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
index 55a0fc87423d3ff1213245e6057ac58c8befcf83..e9dbfb6f11c94cbb678f0c00b081339d8f7b788a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 
 /**
@@ -29,8 +30,7 @@ public interface IEntityTypePropertyTypeBO
     /**
      * Create a new Entity Type - Property Type relation.
      */
-    void createAssignment(String propertyTypeCode, String entityTypeCode, boolean isMandatory,
-            String defaultValue, String section, Long previousETPTOrdinal);
+    void createAssignment(NewETPTAssignment newAssignment);
 
     /**
      * Loads assignments between specified property type and entity type.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IScriptBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IScriptBO.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f577a07d3360963d60d49c4c9424bf664691004
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IScriptBO.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.business.bo;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+
+/**
+ * Business object of a script.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IScriptBO extends IEntityBusinessObject
+{
+
+    /**
+     * Deletes script for specified reason.
+     * 
+     * @param scriptId script technical identifier
+     * @throws UserFailureException if script with given technical identifier is not found.
+     */
+    public void deleteByTechId(TechId scriptId);
+
+    /**
+     * Defines a new script.
+     */
+    public void define(Script script);
+
+    /**
+     * Updates the script.
+     */
+    public void update(IScriptUpdates updates);
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d77b80e383501e2734d77c5839f10645ea4fa97
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ScriptBO.java
@@ -0,0 +1,100 @@
+/*
+ * 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.server.business.bo;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataRetrievalFailureException;
+
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+
+/**
+ * The only productive implementation of {@link IScriptBO}. We are using an interface here to keep
+ * the system testable.
+ * 
+ * @author Izabela Adamczyk
+ */
+public final class ScriptBO extends AbstractBusinessObject implements IScriptBO
+{
+
+    private ScriptPE script;
+
+    public ScriptBO(final IDAOFactory daoFactory, final Session session)
+    {
+        super(daoFactory, session);
+    }
+
+    public void deleteByTechId(TechId groupId) throws UserFailureException
+    {
+        loadDataByTechId(groupId);
+        try
+        {
+            getScriptDAO().delete(script);
+        } catch (final DataAccessException ex)
+        {
+            throwException(ex, String.format("Script '%s'", script.getName()));
+        }
+    }
+
+    public void loadDataByTechId(TechId id)
+    {
+        try
+        {
+            script = getScriptDAO().getByTechId(id);
+        } catch (DataRetrievalFailureException exception)
+        {
+            throw new UserFailureException(exception.getMessage());
+        }
+    }
+
+    public void save() throws UserFailureException
+    {
+        assert script != null : "Script not defined";
+        try
+        {
+            getScriptDAO().createOrUpdate(script);
+        } catch (final DataAccessException e)
+        {
+            throwException(e, "Script '" + script.getName() + "'");
+        }
+    }
+
+    public void define(Script newScript) throws UserFailureException
+    {
+        assert newScript != null : "Unspecified script.";
+        script = new ScriptPE();
+        script.setDatabaseInstance(getHomeDatabaseInstance());
+        script.setName(newScript.getName());
+        script.setDescription(newScript.getDescription());
+        script.setRegistrator(findRegistrator());
+        script.setScript(newScript.getScript());
+    }
+
+    public void update(IScriptUpdates updates)
+    {
+        loadDataByTechId(TechId.create(updates));
+        script.setName(updates.getName());
+        script.setDescription(updates.getDescription());
+        script.setScript(updates.getScript());
+        getScriptDAO().createOrUpdate(script);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
index 4ab246bc718e5316576837ce771ded4b838cdbec..629dd5bc04c534b3692623ac11542a491d00ce6f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDAOFactory.java
@@ -23,7 +23,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 /**
  * A <i>Data Access Object</i> factory.
  * 
- * @author     Franz-Josef Elmer
+ * @author Franz-Josef Elmer
  */
 public interface IDAOFactory extends IAuthorizationDAOFactory
 {
@@ -78,6 +78,11 @@ public interface IDAOFactory extends IAuthorizationDAOFactory
      */
     public IMaterialDAO getMaterialDAO();
 
+    /**
+     * Returns the {@link IScriptDAO} implementation.
+     */
+    public IScriptDAO getScriptDAO();
+
     /** Returns an implementation of {@link ICodeSequenceDAO} */
     public ICodeSequenceDAO getCodeSequenceDAO();
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IScriptDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IScriptDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb5166ca3c25393c2478eb7149528f9594bfacf5
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IScriptDAO.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007 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.server.dataaccess;
+
+import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE;
+
+/**
+ * <i>Data Access Object</i> for {@link ScriptPE}.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IScriptDAO extends IGenericDAO<ScriptPE>
+{
+
+    /**
+     * Creates or updates the specified script.
+     */
+    void createOrUpdate(ScriptPE script);
+
+    /**
+     * Returns script with given name or null if no such script exists.
+     */
+    ScriptPE tryFindByName(String scriptName);
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
index 03455756a26969187672db9e9b7db1dece220455..37dd4161e67de831cc46e005763addfb56deeb70 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DAOFactory.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.ILocatorTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IMaterialDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPropertyTypeDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleTypeDAO;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IScriptDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IVocabularyTermDAO;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.search.HibernateSearchContext;
@@ -93,6 +94,8 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
 
     private final IAuthorizationGroupDAO authorizationGroupDAO;
 
+    private IScriptDAO scriptDAO;
+
     public DAOFactory(final DatabaseConfigurationContext context,
             final SessionFactory sessionFactory, HibernateSearchContext hibernateSearchContext,
             final IFullTextIndexUpdateScheduler fullTextIndexUpdateScheduler)
@@ -114,6 +117,7 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
         permIdDAO = new PermIdDAO(sessionFactory, databaseInstance);
         eventDAO = new EventDAO(sessionFactory, databaseInstance);
         authorizationGroupDAO = new AuthorizationGroupDAO(sessionFactory, databaseInstance);
+        scriptDAO = new ScriptDAO(sessionFactory, databaseInstance);
         final EntityKind[] entityKinds = EntityKind.values();
         for (final EntityKind entityKind : entityKinds)
         {
@@ -214,4 +218,9 @@ public final class DAOFactory extends AuthorizationDAOFactory implements IDAOFac
         return authorizationGroupDAO;
     }
 
+    public IScriptDAO getScriptDAO()
+    {
+        return scriptDAO;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ScriptDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ScriptDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0230b11e415285f5923fd1a2280b52ed046a013
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ScriptDAO.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2007 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.server.dataaccess.db;
+
+import org.apache.log4j.Logger;
+import org.hibernate.Criteria;
+import org.hibernate.SessionFactory;
+import org.hibernate.criterion.Restrictions;
+import org.springframework.jdbc.support.JdbcAccessor;
+import org.springframework.orm.hibernate3.HibernateTemplate;
+
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IScriptDAO;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE;
+
+/**
+ * <i>Data Access Object</i> implementation for {@link ScriptPE}.
+ * 
+ * @author Izabela Adamczyk
+ */
+final class ScriptDAO extends AbstractGenericEntityDAO<ScriptPE> implements IScriptDAO
+{
+
+    /**
+     * This logger does not output any SQL statement. If you want to do so, you had better set an
+     * appropriate debugging level for class {@link JdbcAccessor}. </p>
+     */
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            ScriptDAO.class);
+
+    ScriptDAO(final SessionFactory sessionFactory, final DatabaseInstancePE databaseInstance)
+    {
+        super(sessionFactory, databaseInstance, ScriptPE.class);
+    }
+
+    public void createOrUpdate(ScriptPE script)
+    {
+        assert script != null : "Missing script.";
+        validatePE(script);
+        final HibernateTemplate template = getHibernateTemplate();
+        template.saveOrUpdate(script);
+        template.flush();
+        if (operationLog.isInfoEnabled())
+        {
+            operationLog.info(String.format("SAVE: script '%s'.", script));
+        }
+    }
+
+    public ScriptPE tryFindByName(String scriptName)
+    {
+        assert scriptName != null : "Unspecified script.";
+
+        final Criteria criteria = getSession().createCriteria(ScriptPE.class);
+        criteria.add(Restrictions.eq("name", scriptName));
+        criteria.add(Restrictions.eq("databaseInstance", getDatabaseInstance()));
+        return (ScriptPE) criteria.uniqueResult();
+    }
+
+}
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 748078baa1caae718e25ee872a6eec60aa03a77a..1b6b9fd4abfd9cdb8f09589e5fb22ea7b01a118d 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
@@ -74,6 +74,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -88,6 +89,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -97,6 +99,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -123,6 +126,15 @@ public interface ICommonServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public void keepSessionAlive(String sessionToken);
 
+    /**
+     * Returns all scripts.
+     * 
+     * @return a sorted list of {@link Script}s.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    public List<Script> listScripts(String sessionToken);
+
     /**
      * Returns all spaces which belong to the specified database instance. *
      * 
@@ -141,6 +153,14 @@ public interface ICommonServer extends IServer
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SPACE)
     public void registerSpace(String sessionToken, String spaceCode, String descriptionOrNull);
 
+    /**
+     * Updates a script.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseUpdateModification(value = ObjectKind.SCRIPT)
+    public void updateScript(final String sessionToken, final IScriptUpdates updates);
+
     /**
      * Updates a property type.
      */
@@ -158,6 +178,14 @@ public interface ICommonServer extends IServer
     public void registerAuthorizationGroup(String sessionToken,
             NewAuthorizationGroup newAuthorizationGroup);
 
+    /**
+     * Registers a new script.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.SCRIPT)
+    public void registerScript(String sessionToken, Script script);
+
     /**
      * Deletes selected authorization groups.
      */
@@ -394,9 +422,7 @@ public interface ICommonServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.PROPERTY_TYPE_ASSIGNMENT)
-    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
-            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue, final String section, final Long previousETPTOrdinal);
+    public String assignPropertyType(final String sessionToken, NewETPTAssignment assignment);
 
     /**
      * Update property type assignment to entity type.
@@ -471,6 +497,14 @@ public interface ICommonServer extends IServer
             @AuthorizationGuard(guardClass = SpaceTechIdPredicate.class) List<TechId> spaceIds,
             String reason);
 
+    /**
+     * Deletes specified scripts.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.SCRIPT)
+    public void deleteScripts(String sessionToken, List<TechId> scriptIds);
+
     /**
      * Adds new terms to a vocabulary starting from specified ordinal + 1.
      */
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 0b665d8b0b901433d25b0463711d40095e88bfc8..a469dd557a35a913891fe7adfbfd9b78f4898dfb 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
@@ -36,7 +36,7 @@ public class DatabaseModificationKind implements IsSerializable
         AUTHORIZATION_GROUP, SAMPLE, EXPERIMENT, MATERIAL, DATA_SET, SAMPLE_TYPE, EXPERIMENT_TYPE,
         MATERIAL_TYPE, DATASET_TYPE, FILE_FORMAT_TYPE, PROJECT, SPACE, PROPERTY_TYPE,
         PROPERTY_TYPE_ASSIGNMENT, VOCABULARY, VOCABULARY_TERM, ROLE_ASSIGNMENT, PERSON,
-        GRID_CUSTOM_FILTER, GRID_CUSTOM_COLUMN,
+        GRID_CUSTOM_FILTER, GRID_CUSTOM_COLUMN, SCRIPT,
         // TODO 2010-02-19, PTR: no easy way to extend current modification notification solution in
         // modules
         QUERY
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IScriptUpdates.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IScriptUpdates.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b8e27f6b1865bfd5677901c3a4a8b8a2129c990
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IScriptUpdates.java
@@ -0,0 +1,33 @@
+/*
+ * 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.shared.basic.dto;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
+
+/**
+ * Description of the updates which should be performed on a script.
+ * 
+ * @author Izabela Adamczyk
+ */
+public interface IScriptUpdates extends IIdHolder
+{
+    String getDescription();
+
+    String getName();
+
+    String getScript();
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewETPTAssignment.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewETPTAssignment.java
new file mode 100644
index 0000000000000000000000000000000000000000..69a02c96ff74009e00028442c34afd17ae62c6ba
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/NewETPTAssignment.java
@@ -0,0 +1,159 @@
+/*
+ * 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.shared.basic.dto;
+
+import java.io.Serializable;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Stores data needed to create new entity type-property type assignment.
+ * 
+ * @author Izabela Adamczyk
+ */
+public class NewETPTAssignment implements IsSerializable, Serializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private EntityKind entityKind;
+
+    private String propertyTypeCode;
+
+    private String entityTypeCode;
+
+    private boolean mandatory;
+
+    private String defaultValue;
+
+    private String section;
+
+    private Long ordinal;
+
+    private String scriptName;
+
+    private boolean dynamic;
+
+    public NewETPTAssignment()
+    {
+    }
+
+    public NewETPTAssignment(EntityKind entityKind, String propertyTypeCode, String entityTypeCode,
+            boolean manadatory, String defaultValue, String section, Long ordinal, boolean dynamic,
+            String scriptOrNull)
+    {
+        this.entityKind = entityKind;
+        this.propertyTypeCode = propertyTypeCode;
+        this.entityTypeCode = entityTypeCode;
+        this.mandatory = manadatory;
+        this.defaultValue = defaultValue;
+        this.section = section;
+        this.ordinal = ordinal;
+        this.dynamic = dynamic;
+        this.scriptName = scriptOrNull;
+    }
+
+    public EntityKind getEntityKind()
+    {
+        return entityKind;
+    }
+
+    public void setEntityKind(EntityKind entityKind)
+    {
+        this.entityKind = entityKind;
+    }
+
+    public String getPropertyTypeCode()
+    {
+        return propertyTypeCode;
+    }
+
+    public void setPropertyTypeCode(String propertyTypeCode)
+    {
+        this.propertyTypeCode = propertyTypeCode;
+    }
+
+    public String getEntityTypeCode()
+    {
+        return entityTypeCode;
+    }
+
+    public void setEntityTypeCode(String entityTypeCode)
+    {
+        this.entityTypeCode = entityTypeCode;
+    }
+
+    public boolean isMandatory()
+    {
+        return mandatory;
+    }
+
+    public void setMandatory(boolean mandatory)
+    {
+        this.mandatory = mandatory;
+    }
+
+    public String getDefaultValue()
+    {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(String defaultValue)
+    {
+        this.defaultValue = defaultValue;
+    }
+
+    public String getSection()
+    {
+        return section;
+    }
+
+    public void setSection(String section)
+    {
+        this.section = section;
+    }
+
+    public Long getOrdinal()
+    {
+        return ordinal;
+    }
+
+    public void setOrdinal(Long ordinal)
+    {
+        this.ordinal = ordinal;
+    }
+
+    public String getScriptName()
+    {
+        return scriptName;
+    }
+
+    public void setScriptName(String scriptName)
+    {
+        this.scriptName = scriptName;
+    }
+
+    public boolean isDynamic()
+    {
+        return dynamic;
+    }
+
+    public void setDynamic(boolean dynamic)
+    {
+        this.dynamic = dynamic;
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Script.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Script.java
index 764b79f4ca561e24d7549bf3747b4a7f4b86c9e9..12c9c904cee0621a7459366b49a5205e19fea3d6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Script.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/Script.java
@@ -23,7 +23,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
  * 
  * @author Izabela Adamczyk
  */
-public class Script extends AbstractRegistrationHolder implements Comparable<Script>, IIdHolder
+public class Script extends AbstractRegistrationHolder implements Comparable<Script>, IIdHolder,
+        IScriptUpdates
 {
     private static final long serialVersionUID = ServiceVersionHolder.VERSION;
 
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 9897f07a2ce95860ac4daa2cf44b63a78bd078f9..6ffda1391233e73d6b070ba136044361a68756e8 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
@@ -266,6 +266,7 @@ var common = {
   //
   // Property Type Assignments Browser
   //
+  dynamic: "Dynamic",
   is_dynamic: "Dynamic?",
   script: "Script",
   unassign_button_label: "Release Assignment",
@@ -675,6 +676,13 @@ default_group: "Default Space",
  add_new_column: "Add a New Column",
  how_to_address: "How To Address", 
  insert_columns: "Insert Columns", 
+
+
+//
+// Script Browser
+//
+add_script_title: "Add a new script",
+title_choose_script: "Choose a Script",
  
  // LAST LINE: KEEP IT AT THE END
   lastline: "" // we need a line without a comma
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
index 8c7a4696425548a62ef514cce4700a874891d017..8afad3caa59c2c7e6bd8db0d35ba581c22229afe 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
@@ -49,17 +49,18 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LastModificationState;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 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.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
@@ -422,8 +423,8 @@ public final class CommonServerTest extends AbstractServerTestCase
             fail("UserFailureException expected");
         } catch (final UserFailureException e)
         {
-            assertEquals("Following persons already exist: [" + CommonTestUtils.USER_ID + "]", e
-                    .getMessage());
+            assertEquals("Following persons already exist: [" + CommonTestUtils.USER_ID + "]",
+                    e.getMessage());
         }
 
         context.assertIsSatisfied();
@@ -594,7 +595,9 @@ public final class CommonServerTest extends AbstractServerTestCase
         prepareGetSession();
         final List<EntityTypePE> types = new ArrayList<EntityTypePE>();
         final ExperimentTypePE experimentTypePE = CommonTestUtils.createExperimentType();
-        final ExperimentType experimentType = ExperimentTranslator.translate(experimentTypePE, new HashMap<PropertyTypePE, PropertyType>());
+        final ExperimentType experimentType =
+                ExperimentTranslator.translate(experimentTypePE,
+                        new HashMap<PropertyTypePE, PropertyType>());
         types.add(experimentTypePE);
         context.checking(new Expectations()
             {
@@ -1134,6 +1137,9 @@ public final class CommonServerTest extends AbstractServerTestCase
         final boolean mandatory = true;
         final String value = "50m";
         final String section = "section 1";
+        final NewETPTAssignment newAssignment =
+                new NewETPTAssignment(entityKind, propertyTypeCode, entityTypeCode, mandatory,
+                        value, section, 1L, false, null);
         context.checking(new Expectations()
             {
                 {
@@ -1141,14 +1147,12 @@ public final class CommonServerTest extends AbstractServerTestCase
                             DtoConverters.convertEntityKind(entityKind));
                     will(returnValue(entityTypePropertyTypeBO));
 
-                    one(entityTypePropertyTypeBO).createAssignment(propertyTypeCode,
-                            entityTypeCode, mandatory, value, section, 1L);
+                    one(entityTypePropertyTypeBO).createAssignment(newAssignment);
                 }
             });
         assertEquals(
                 "Mandatory property type 'USER.DISTANCE' successfully assigned to experiment type 'ARCHERY'",
-                createServer().assignPropertyType(SESSION_TOKEN, entityKind, propertyTypeCode,
-                        entityTypeCode, mandatory, value, section, 1L));
+                createServer().assignPropertyType(SESSION_TOKEN, newAssignment));
         context.assertIsSatisfied();
     }
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
index 589770143b43191b151bae29e51202ba019de953..1647bc660c084682523e4d9372faa4380b45e60a 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
@@ -25,6 +25,7 @@ import org.jmock.Expectations;
 import org.testng.annotations.Test;
 
 import ch.rinn.restrictions.Friend;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE;
@@ -139,8 +140,12 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
                 }
             });
         final EntityTypePropertyTypeBO bo = createEntityTypePropertyTypeBO(EntityKind.EXPERIMENT);
-        bo.createAssignment(propertyType.getCode(), experimentType.getCode(), mandatory,
-                defaultValue, section, 1L);
+        NewETPTAssignment newAssignment =
+                new NewETPTAssignment(
+                        ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind.EXPERIMENT,
+                        propertyType.getCode(), experimentType.getCode(), mandatory, defaultValue,
+                        section, 1L, false, null);
+        bo.createAssignment(newAssignment);
 
         context.assertIsSatisfied();
     }
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 748078baa1caae718e25ee872a6eec60aa03a77a..1b6b9fd4abfd9cdb8f09589e5fb22ea7b01a118d 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
@@ -74,6 +74,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomColumn;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.GridCustomFilter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IExpressionUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IPropertyTypeUpdates;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IScriptUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISpaceUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyTermUpdates;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IVocabularyUpdates;
@@ -88,6 +89,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewETPTAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewVocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
@@ -97,6 +99,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
@@ -123,6 +126,15 @@ public interface ICommonServer extends IServer
     @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
     public void keepSessionAlive(String sessionToken);
 
+    /**
+     * Returns all scripts.
+     * 
+     * @return a sorted list of {@link Script}s.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    public List<Script> listScripts(String sessionToken);
+
     /**
      * Returns all spaces which belong to the specified database instance. *
      * 
@@ -141,6 +153,14 @@ public interface ICommonServer extends IServer
     @DatabaseCreateOrDeleteModification(value = ObjectKind.SPACE)
     public void registerSpace(String sessionToken, String spaceCode, String descriptionOrNull);
 
+    /**
+     * Updates a script.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseUpdateModification(value = ObjectKind.SCRIPT)
+    public void updateScript(final String sessionToken, final IScriptUpdates updates);
+
     /**
      * Updates a property type.
      */
@@ -158,6 +178,14 @@ public interface ICommonServer extends IServer
     public void registerAuthorizationGroup(String sessionToken,
             NewAuthorizationGroup newAuthorizationGroup);
 
+    /**
+     * Registers a new script.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.SCRIPT)
+    public void registerScript(String sessionToken, Script script);
+
     /**
      * Deletes selected authorization groups.
      */
@@ -394,9 +422,7 @@ public interface ICommonServer extends IServer
     @Transactional
     @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
     @DatabaseCreateOrDeleteModification(value = ObjectKind.PROPERTY_TYPE_ASSIGNMENT)
-    public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
-            final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue, final String section, final Long previousETPTOrdinal);
+    public String assignPropertyType(final String sessionToken, NewETPTAssignment assignment);
 
     /**
      * Update property type assignment to entity type.
@@ -471,6 +497,14 @@ public interface ICommonServer extends IServer
             @AuthorizationGuard(guardClass = SpaceTechIdPredicate.class) List<TechId> spaceIds,
             String reason);
 
+    /**
+     * Deletes specified scripts.
+     */
+    @Transactional
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @DatabaseCreateOrDeleteModification(value = ObjectKind.SCRIPT)
+    public void deleteScripts(String sessionToken, List<TechId> scriptIds);
+
     /**
      * Adds new terms to a vocabulary starting from specified ordinal + 1.
      */