From 499bca51d0760a2774f1c2d645d40b9366d4ded8 Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Fri, 7 Sep 2012 15:19:36 +0000
Subject: [PATCH] SWE-2 / SP-263: Sample creation, introduced builders to more
 compact and readable tests.

SVN: 26554
---
 .../client/application/menu/top/NewMenu.java  |   2 +-
 ...AbstractGenericSampleRegisterEditForm.java |   1 +
 .../openbis/uitest/AuthorizationTest.java     |   1 -
 .../uitest/PropertyTypeAssignmentTest.java    |  15 +-
 .../cisd/openbis/uitest/PropertyTypeTest.java |   7 +-
 .../cisd/openbis/uitest/SampleTest.java       |  64 +++++++++
 .../cisd/openbis/uitest/SampleTypeTest.java   |  18 +--
 .../cisd/openbis/uitest/SpaceTest.java        |   4 +-
 .../cisd/openbis/uitest/VocabularyTest.java   |   4 +-
 .../uitest/infra/ApplicationRunner.java       |  47 ++++--
 .../openbis/uitest/infra/SeleniumTest.java    |  57 +++++++-
 .../matcher/BrowserListsElementMatcher.java   |   2 +-
 .../openbis/uitest/page/NavigationPage.java   |  10 ++
 .../cisd/openbis/uitest/page/Page.java        |   6 +-
 .../openbis/uitest/page/menu/NewMenu.java     |  36 +++++
 .../page/tab/AssignSamplePropertyType.java    |  15 +-
 .../uitest/page/tab/RegisterSample.java       |  83 +++++++++++
 .../uitest/page/tab/SampleBrowser.java        |  33 +++--
 .../cisd/openbis/uitest/type/Builder.java     |  25 ++++
 .../cisd/openbis/uitest/type/Experiment.java  |  73 ++++++++++
 .../ExperimentType.java}                      |  13 +-
 .../cisd/openbis/uitest/type/Project.java     |  72 ++++++++++
 .../openbis/uitest/type/PropertyType.java     |  69 ++++-----
 .../uitest/type/PropertyTypeAssignment.java   |  33 ++++-
 .../type/PropertyTypeAssignmentBuilder.java   |  80 +++++++++++
 .../uitest/type/PropertyTypeBuilder.java      |  64 +++++++++
 .../cisd/openbis/uitest/type/Sample.java      | 116 +++++++++++++++
 .../openbis/uitest/type/SampleBuilder.java    |  82 +++++++++++
 .../cisd/openbis/uitest/type/SampleType.java  | 134 ++++++++----------
 .../uitest/type/SampleTypeBuilder.java        |  94 ++++++++++++
 .../uitest/type/SampleTypeUpdateBuilder.java  |  54 +++++++
 .../cisd/openbis/uitest/type/Space.java       |  42 +++---
 .../openbis/uitest/type/SpaceBuilder.java     |  47 ++++++
 .../openbis/uitest/type/UpdateBuilder.java    |  25 ++++
 .../cisd/openbis/uitest/type/Vocabulary.java  |  57 +++-----
 .../uitest/type/VocabularyBuilder.java        |  57 ++++++++
 36 files changed, 1285 insertions(+), 257 deletions(-)
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTest.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
 rename ui-test/source/java/ch/systemsx/cisd/openbis/uitest/{page/dialog/AddSampleDialog.java => type/ExperimentType.java} (80%)
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeUpdateBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/UpdateBuilder.java
 create mode 100644 ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/NewMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/NewMenu.java
index a0d7cdd2399..0d16ea42ff9 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/NewMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/NewMenu.java
@@ -35,6 +35,7 @@ public class NewMenu extends TopMenuItem
     public NewMenu(IMessageProvider messageProvider, ComponentProvider componentProvider)
     {
         super(messageProvider.getMessage(Dict.MENU_NEW));
+        setId("new_menu");
 
         Menu submenu = new Menu();
         submenu.add(new ActionMenu(TopMenu.ActionMenuKind.PROJECT_MENU_NEW, messageProvider,
@@ -45,5 +46,4 @@ public class NewMenu extends TopMenuItem
                 componentProvider.getSampleRegistration()));
         setMenu(submenu);
     }
-
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
index f410a64ce90..b234e7b9323 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java
@@ -304,6 +304,7 @@ abstract public class AbstractGenericSampleRegisterEditForm extends
     {
         groupSelectionWidget =
                 new SpaceSelectionWidget(viewContext, getId(), true, false, initialGroupCodeOrNull);
+        groupSelectionWidget.setId("register-sample-space-selection");
         FieldUtil.markAsMandatory(groupSelectionWidget);
         groupSelectionWidget.setFieldLabel(viewContext.getMessage(Dict.GROUP));
         parentButton =
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/AuthorizationTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/AuthorizationTest.java
index 4fb27c59f60..a4d637c4670 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/AuthorizationTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/AuthorizationTest.java
@@ -46,7 +46,6 @@ public class AuthorizationTest extends SeleniumTest
         openbis.login(User.ADMIN);
         try
         {
-
             openbis.browseToRoleAssignmentBrowser();
             assertThat(browser(), isShowing(RoleAssignmentBrowser.class));
         } finally
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeAssignmentTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeAssignmentTest.java
index 066071562f2..e8e85fc3c23 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeAssignmentTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeAssignmentTest.java
@@ -21,9 +21,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.uitest.infra.SeleniumTest;
-import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignment;
-import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeDataType;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 
 /**
@@ -36,15 +34,12 @@ public class PropertyTypeAssignmentTest extends SeleniumTest
     @Test
     public void newPropertyTypeAssignmentIsListedInPropertyTypeAssignmentBrowser() throws Exception
     {
-        PropertyType propertyType = new PropertyType().setDataType(PropertyTypeDataType.INTEGER);
-        openbis.create(propertyType);
+        SampleType sampleType = create(aSampleType());
 
-        SampleType sampleType = new SampleType();
-        openbis.create(sampleType);
+        PropertyTypeAssignment assignment =
+                create(aSamplePropertyTypeAssignment().withSampleType(sampleType).thatIsMandatory()
+                        .havingInitialValueOf("32"));
 
-        openbis.assign(propertyType, sampleType, "32");
-
-        assertThat(propertyTypeAssignmentBrowser(), lists(new PropertyTypeAssignment(propertyType,
-                sampleType)));
+        assertThat(propertyTypeAssignmentBrowser(), lists(assignment));
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeTest.java
index 43aaf183053..5610071c494 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/PropertyTypeTest.java
@@ -22,7 +22,6 @@ import org.testng.annotations.Test;
 
 import ch.systemsx.cisd.openbis.uitest.infra.SeleniumTest;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
-import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
 
 /**
  * @author anttil
@@ -34,11 +33,7 @@ public class PropertyTypeTest extends SeleniumTest
     @Test
     public void newPropertyTypeIsListedInPropertyTypeBrowser() throws Exception
     {
-        Vocabulary vocabulary = new Vocabulary();
-        openbis.create(vocabulary);
-
-        PropertyType propertyType = new PropertyType(vocabulary);
-        openbis.create(propertyType);
+        PropertyType propertyType = create(aPropertyType());
 
         assertThat(propertyTypeBrowser(), lists(propertyType));
     }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTest.java
new file mode 100644
index 00000000000..277bef8873d
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.uitest.infra.SeleniumTest;
+import ch.systemsx.cisd.openbis.uitest.type.Sample;
+
+/**
+ * @author anttil
+ */
+@Test(groups =
+    { "login-admin" })
+public class SampleTest extends SeleniumTest
+{
+    @Test
+    public void newSampleIsListedInSampleBrowser() throws Exception
+    {
+        Sample sample = create(aSample());
+
+        assertThat(sampleBrowser(), lists(sample));
+    }
+
+    @Test
+    public void propertiesOfSampleTypeAreAskedForInSampleRegistration() throws Exception
+    {
+        /*
+        PropertyType booleanType = create(aBooleanPropertyType().withLabel("boolean"));
+        SampleType sampleType = create(aSampleType().withProperties(booleanType));
+
+        assertThat(sampleRegistrationPageForSampleType(type), containsFields("boolean"));
+        */
+    }
+
+    @Test
+    public void vocabulariesLinkToExternalPagesFromSampleBrowser() throws Exception
+    {
+
+    }
+
+    @Test
+    public void visibilityOfPropertiesOfSampleTypeCanBeSetFromSampleBrowserSettings()
+            throws Exception
+    {
+
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTypeTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTypeTest.java
index eb6a0d6d204..25d6fa8411f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTypeTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SampleTypeTest.java
@@ -35,9 +35,7 @@ public class SampleTypeTest extends SeleniumTest
     @Test
     public void cannotSaveSampleTypeWithInvalidCode()
     {
-        SampleType sampleType = new SampleType().setCode("invalid code");
-
-        openbis.create(sampleType);
+        create(aSampleType().withCode("invalid code"));
 
         assertThat(browser(), isShowing(AddSampleTypeDialog.class));
 
@@ -47,9 +45,7 @@ public class SampleTypeTest extends SeleniumTest
     @Test
     public void newSampleTypeIsListedInSampleTypeBrowser()
     {
-        SampleType sampleType = new SampleType();
-
-        openbis.create(sampleType);
+        SampleType sampleType = create(aSampleType());
 
         assertThat(sampleTypeBrowser(), lists(sampleType));
     }
@@ -57,9 +53,7 @@ public class SampleTypeTest extends SeleniumTest
     @Test
     public void nonListableSampleTypeIsNotVisibleInSampleBrowserDropDownMenu()
     {
-        SampleType sampleType = new SampleType().setListable(false);
-
-        openbis.create(sampleType);
+        SampleType sampleType = create(aSampleType().thatIsListable());
 
         assertThat(sampleBrowser(), doesNotShowInToolBar(sampleType));
     }
@@ -67,11 +61,9 @@ public class SampleTypeTest extends SeleniumTest
     @Test
     public void changingSampleTypeToBeListableMakesItVisibleInSampleBrowserDropDownMenu()
     {
-        SampleType sampleType = new SampleType().setListable(false);
-        openbis.create(sampleType);
+        SampleType sampleType = create(aSampleType().thatIsNotListable());
 
-        sampleType.setListable(true);
-        openbis.update(sampleType);
+        perform(anUpdateOf(sampleType).settingItListable());
 
         assertThat(sampleBrowser(), showsInToolBar(sampleType));
     }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SpaceTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SpaceTest.java
index cfc6b14f9d7..76c211fb07c 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SpaceTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/SpaceTest.java
@@ -15,9 +15,7 @@ public class SpaceTest extends SeleniumTest
     @Test
     public void newSpaceIsListedInSpaceBrowser() throws Exception
     {
-        Space space = new Space();
-
-        openbis.create(space);
+        Space space = create(aSpace());
 
         assertThat(spaceBrowser(), lists(space));
     }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/VocabularyTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/VocabularyTest.java
index 9e928fb690f..8a09b77b8a1 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/VocabularyTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/VocabularyTest.java
@@ -15,9 +15,7 @@ public class VocabularyTest extends SeleniumTest
     @Test
     public void newVocabularyIsListedInVocabularyBrowser() throws Exception
     {
-        Vocabulary vocabulary = new Vocabulary();
-
-        openbis.create(vocabulary);
+        Vocabulary vocabulary = create(aVocabulary());
 
         assertThat(vocabularyBrowser(), lists(vocabulary));
     }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
index 5130be06892..4a727960c54 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/ApplicationRunner.java
@@ -26,12 +26,15 @@ import ch.systemsx.cisd.openbis.uitest.page.tab.AddPropertyType;
 import ch.systemsx.cisd.openbis.uitest.page.tab.AssignSamplePropertyType;
 import ch.systemsx.cisd.openbis.uitest.page.tab.PropertyTypeAssignmentBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.PropertyTypeBrowser;
+import ch.systemsx.cisd.openbis.uitest.page.tab.RegisterSample;
 import ch.systemsx.cisd.openbis.uitest.page.tab.RoleAssignmentBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.SampleBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.SampleTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.SpaceBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.VocabularyBrowser;
 import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignment;
+import ch.systemsx.cisd.openbis.uitest.type.Sample;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 import ch.systemsx.cisd.openbis.uitest.type.Space;
 import ch.systemsx.cisd.openbis.uitest.type.Vocabulary;
@@ -49,52 +52,61 @@ public class ApplicationRunner
         this.proxy = proxy;
     }
 
-    public void create(Space space)
+    public Space create(Space space)
     {
         AddSpaceDialog dialog = browseToAddSpaceDialog();
         dialog.fillWith(space);
         dialog.save();
+        return space;
     }
 
-    public void create(SampleType sampleType)
+    public SampleType create(SampleType sampleType)
     {
         AddSampleTypeDialog dialog = browseToAddSampleTypeDialog();
         dialog.fillWith(sampleType);
         dialog.save();
+        return sampleType;
     }
 
-    public void create(Vocabulary vocabulary)
+    public Vocabulary create(Vocabulary vocabulary)
     {
         AddVocabularyDialog dialog = browseToAddVocabularyDialog();
         dialog.fillWith(vocabulary);
         dialog.save();
+        return vocabulary;
     }
 
-    public void create(PropertyType propertyType)
+    public PropertyType create(PropertyType propertyType)
     {
         AddPropertyType dialog = browseToAddPropertyType();
         dialog.fillWith(propertyType);
         dialog.save();
+        return propertyType;
     }
 
-    public void update(SampleType sampleType)
+    public Sample create(Sample sample)
     {
-        SampleTypeBrowser sampleTypeBrowser = browseToSampleTypeBrowser();
-        EditSampleTypeDialog dialog = sampleTypeBrowser.editSampleType(sampleType);
-        dialog.fillWith(sampleType);
-        dialog.save();
+        RegisterSample register = browseToRegisterSample();
+        register.selectSampleType(sample.getType());
+        register.fillWith(sample);
+        register.save();
+        return sample;
     }
 
-    public void assign(PropertyType propertyType, SampleType sampleType)
+    public PropertyTypeAssignment create(PropertyTypeAssignment assignment)
     {
-        assign(propertyType, sampleType, null);
+        AssignSamplePropertyType assign = browseToAssignSamplePropertyType();
+        assign.fillWith(assignment);
+        assign.save();
+        return assignment;
     }
 
-    public void assign(PropertyType propertyType, SampleType sampleType, String initialValue)
+    public void update(SampleType sampleType)
     {
-        AssignSamplePropertyType assign = browseToAssignSamplePropertyType();
-        assign.fillWith(propertyType, sampleType, initialValue);
-        assign.save();
+        SampleTypeBrowser sampleTypeBrowser = browseToSampleTypeBrowser();
+        EditSampleTypeDialog dialog = sampleTypeBrowser.editSampleType(sampleType);
+        dialog.fillWith(sampleType);
+        dialog.save();
     }
 
     public void login(String userName, String password)
@@ -174,6 +186,11 @@ public class ApplicationRunner
         return getMenus().admin().metadata().propertyTypeAssignments();
     }
 
+    public RegisterSample browseToRegisterSample()
+    {
+        return getMenus().newMenu().sample();
+    }
+
     public void closeAllTabs()
     {
         getMenus().closeTabs();
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/SeleniumTest.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/SeleniumTest.java
index 4de3e6cde6a..c4e0d9dc1d1 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/SeleniumTest.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/SeleniumTest.java
@@ -45,7 +45,16 @@ import ch.systemsx.cisd.openbis.uitest.page.tab.SampleBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.SampleTypeBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.SpaceBrowser;
 import ch.systemsx.cisd.openbis.uitest.page.tab.VocabularyBrowser;
+import ch.systemsx.cisd.openbis.uitest.type.Builder;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignmentBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.SampleBuilder;
 import ch.systemsx.cisd.openbis.uitest.type.SampleType;
+import ch.systemsx.cisd.openbis.uitest.type.SampleTypeBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.SampleTypeUpdateBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.SpaceBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.UpdateBuilder;
+import ch.systemsx.cisd.openbis.uitest.type.VocabularyBuilder;
 
 public abstract class SeleniumTest
 {
@@ -61,6 +70,7 @@ public abstract class SeleniumTest
     public void initWebDriver()
     {
         /*
+
         System.setProperty("webdriver.firefox.bin",
                 "/Users/anttil/Desktop/Firefox 10.app/Contents/MacOS/firefox");
 
@@ -152,7 +162,7 @@ public abstract class SeleniumTest
 
     protected SampleBrowser sampleBrowser()
     {
-        return openbis.browseToSampleBrowser();
+        return openbis.browseToSampleBrowser().allSpaces();
     }
 
     protected SampleTypeBrowser sampleTypeBrowser()
@@ -199,4 +209,49 @@ public abstract class SeleniumTest
     {
         return new BrowserListsElementMatcher(browsable);
     }
+
+    protected <T> T create(Builder<T> builder)
+    {
+        return builder.build();
+    }
+
+    protected SpaceBuilder aSpace()
+    {
+        return new SpaceBuilder(openbis);
+    }
+
+    protected SampleTypeBuilder aSampleType()
+    {
+        return new SampleTypeBuilder(openbis);
+    }
+
+    protected SampleBuilder aSample()
+    {
+        return new SampleBuilder(openbis);
+    }
+
+    protected VocabularyBuilder aVocabulary()
+    {
+        return new VocabularyBuilder(openbis);
+    }
+
+    protected PropertyTypeBuilder aPropertyType()
+    {
+        return new PropertyTypeBuilder(openbis);
+    }
+
+    protected PropertyTypeAssignmentBuilder aSamplePropertyTypeAssignment()
+    {
+        return new PropertyTypeAssignmentBuilder(openbis);
+    }
+
+    protected SampleTypeUpdateBuilder anUpdateOf(SampleType type)
+    {
+        return new SampleTypeUpdateBuilder(openbis, type);
+    }
+
+    protected void perform(UpdateBuilder builder)
+    {
+        builder.update();
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
index eadf0dbd72c..79cc3f3681a 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/infra/matcher/BrowserListsElementMatcher.java
@@ -40,7 +40,7 @@ public class BrowserListsElementMatcher extends
     @Override
     public void describeTo(Description description)
     {
-        description.appendText("SampleTypeBrowser that contains element " + this.expected);
+        description.appendText("Browser that contains element " + this.expected);
     }
 
     @Override
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/NavigationPage.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/NavigationPage.java
index fb20af20e0b..59a6a410bb8 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/NavigationPage.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/NavigationPage.java
@@ -23,6 +23,7 @@ import org.openqa.selenium.support.FindBy;
 
 import ch.systemsx.cisd.openbis.uitest.page.menu.AdminMenu;
 import ch.systemsx.cisd.openbis.uitest.page.menu.BrowseMenu;
+import ch.systemsx.cisd.openbis.uitest.page.menu.NewMenu;
 import ch.systemsx.cisd.openbis.uitest.page.menu.UserMenu;
 
 /**
@@ -39,6 +40,9 @@ public abstract class NavigationPage extends Page
     @FindBy(id = "browse_menu")
     private WebElement browseMenuButton;
 
+    @FindBy(id = "new_menu")
+    private WebElement newMenuButton;
+
     @FindBy(className = "x-tab-strip-close")
     private List<WebElement> tabCloseButtons;
 
@@ -60,6 +64,12 @@ public abstract class NavigationPage extends Page
         return get(BrowseMenu.class);
     }
 
+    public NewMenu newMenu()
+    {
+        newMenuButton.click();
+        return get(NewMenu.class);
+    }
+
     public void closeTabs()
     {
         for (WebElement e : tabCloseButtons)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/Page.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/Page.java
index aa027d56ce3..38aa9352c0d 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/Page.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/Page.java
@@ -28,6 +28,7 @@ import java.util.List;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebDriver;
 import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
 import org.openqa.selenium.support.ui.ExpectedCondition;
 import org.openqa.selenium.support.ui.WebDriverWait;
 
@@ -112,12 +113,13 @@ public abstract class Page
         {
             if (choice.getText().equalsIgnoreCase(text))
             {
-                choice.click();
+                Actions builder = new Actions(SeleniumTest.driver);
+                builder.moveToElement(choice).click(choice).build().perform();
                 return;
             }
             found.add(choice.getText());
         }
-        throw new IllegalArgumentException("Selection " + text + " not found");
+        throw new IllegalArgumentException("Selection " + text + " not found, got " + found);
     }
 
     protected void checkbox(WebElement box, boolean check)
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
new file mode 100644
index 00000000000..bcf8993f36f
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/menu/NewMenu.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.page.menu;
+
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+import ch.systemsx.cisd.openbis.uitest.page.Page;
+import ch.systemsx.cisd.openbis.uitest.page.tab.RegisterSample;
+
+public class NewMenu extends Page
+{
+
+    @FindBy(id = "openbis_top-menu_SAMPLE_MENU_NEW")
+    private WebElement sample;
+
+    public RegisterSample sample()
+    {
+        sample.click();
+        return get(RegisterSample.class);
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
index 436875b2f32..d074d063a4e 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/AssignSamplePropertyType.java
@@ -24,8 +24,7 @@ import org.openqa.selenium.support.FindBys;
 
 import ch.systemsx.cisd.openbis.uitest.infra.NotAlwaysPresent;
 import ch.systemsx.cisd.openbis.uitest.page.NavigationPage;
-import ch.systemsx.cisd.openbis.uitest.type.PropertyType;
-import ch.systemsx.cisd.openbis.uitest.type.SampleType;
+import ch.systemsx.cisd.openbis.uitest.type.PropertyTypeAssignment;
 
 public class AssignSamplePropertyType extends NavigationPage
 {
@@ -61,19 +60,19 @@ public class AssignSamplePropertyType extends NavigationPage
     @FindBy(id = "openbis_property-type-assignment_SAMPLEsave-button")
     private WebElement saveButton;
 
-    public void fillWith(PropertyType propertyType, SampleType sampleType, String initialValue)
+    public void fillWith(PropertyTypeAssignment assignment)
     {
         this.propertyTypeDropDownOpener.click();
-        select(propertyTypeChoices, propertyType.getLabel());
+        select(propertyTypeChoices, assignment.getPropertyType().getLabel());
 
         this.sampleTypeDropDownOpener.click();
-        select(sampleTypeChoices, sampleType.getCode());
+        select(sampleTypeChoices, assignment.getSampleType().getCode());
 
-        checkbox(mandatoryCheckbox, initialValue != null);
+        checkbox(mandatoryCheckbox, assignment.isMandatory());
 
-        if (initialValue != null)
+        if (assignment.getInitialValue() != null)
         {
-            this.initialValue.sendKeys(initialValue);
+            this.initialValue.sendKeys(assignment.getInitialValue());
         }
     }
 
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
new file mode 100644
index 00000000000..64b3cb8f4ab
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/RegisterSample.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.page.tab;
+
+import java.util.List;
+
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.FindBys;
+
+import ch.systemsx.cisd.openbis.uitest.infra.NotAlwaysPresent;
+import ch.systemsx.cisd.openbis.uitest.page.NavigationPage;
+import ch.systemsx.cisd.openbis.uitest.type.Sample;
+import ch.systemsx.cisd.openbis.uitest.type.SampleType;
+
+public class RegisterSample extends NavigationPage
+{
+
+    @FindBys(
+        {
+                @FindBy(id = "openbis_select_sample-typeopenbis_sample-registration"),
+                @FindBy(xpath = "img") })
+    private WebElement sampleTypeList;
+
+    @FindBy(className = "x-combo-list-item")
+    private List<WebElement> sampleTypeChoices;
+
+    @NotAlwaysPresent
+    @FindBy(id = "openbis_generic-sample-register_formcode-input")
+    private WebElement code;
+
+    @NotAlwaysPresent
+    @FindBy(id = "openbis_generic-sample-register_formexperiment-input")
+    private WebElement experiment;
+
+    @NotAlwaysPresent
+    @FindBys(
+        {
+                @FindBy(id = "register-sample-space-selection"),
+                @FindBy(xpath = "img") })
+    private WebElement spaceList;
+
+    @FindBy(className = "x-combo-list-item")
+    private List<WebElement> spaceChoices;
+
+    @NotAlwaysPresent
+    @FindBy(id = "openbis_generic-sample-register_formsave-button")
+    private WebElement saveButton;
+
+    public void fillWith(Sample sample)
+    {
+        code.sendKeys(sample.getCode());
+        spaceList.click();
+        select(spaceChoices, sample.getSpace().getCode());
+    }
+
+    public RegisterSample selectSampleType(SampleType sampleType)
+    {
+        sampleTypeList.click();
+        select(sampleTypeChoices, sampleType.getCode());
+        return get(RegisterSample.class);
+    }
+
+    public RegisterSample save()
+    {
+        this.saveButton.click();
+        return get(RegisterSample.class);
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
index 52c1cdbe9c5..c99db8a7b64 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/tab/SampleBrowser.java
@@ -24,7 +24,7 @@ import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.FindBys;
 
 import ch.systemsx.cisd.openbis.uitest.page.BrowserPage;
-import ch.systemsx.cisd.openbis.uitest.page.dialog.AddSampleDialog;
+import ch.systemsx.cisd.openbis.uitest.type.SampleType;
 
 public class SampleBrowser extends BrowserPage
 {
@@ -46,17 +46,26 @@ public class SampleBrowser extends BrowserPage
 
     @FindBys(
         {
-                @FindBy(id = "openbis_select_group-selectsample-browser-toolbar"),
+                @FindBy(id = "openbis_select_sample-typesample-browser-toolbar"),
                 @FindBy(xpath = "img") })
     private WebElement sampleTypeList;
 
     @FindBy(className = "x-combo-list-item")
-    private List<WebElement> choices;
+    private List<WebElement> sampleTypeChoices;
 
-    public AddSampleDialog addSample()
+    @FindBys(
+        {
+                @FindBy(id = "openbis_select_group-selectsample-browser-toolbar"),
+                @FindBy(xpath = "img") })
+    private WebElement spaceList;
+
+    @FindBy(className = "x-combo-list-item")
+    private List<WebElement> spaceChoices;
+
+    public RegisterSample addSample()
     {
         addSampleButton.click();
-        return get(AddSampleDialog.class);
+        return get(RegisterSample.class);
     }
 
     @Override
@@ -71,10 +80,18 @@ public class SampleBrowser extends BrowserPage
         return this.data;
     }
 
-    public SampleBrowser selectSampleType(String sampleType)
+    public SampleBrowser selectSampleType(SampleType sampleType)
     {
         sampleTypeList.click();
-        select(choices, sampleType);
+        select(sampleTypeChoices, sampleType.getCode());
+        return get(SampleBrowser.class);
+    }
+
+    public SampleBrowser allSpaces()
+    {
+        spaceList.click();
+        select(spaceChoices, "(all)");
+
         return get(SampleBrowser.class);
     }
 
@@ -83,7 +100,7 @@ public class SampleBrowser extends BrowserPage
         List<String> sampleTypes = new ArrayList<String>();
 
         sampleTypeList.click();
-        for (WebElement choice : choices)
+        for (WebElement choice : sampleTypeChoices)
         {
             sampleTypes.add(choice.getText());
         }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
new file mode 100644
index 00000000000..5d6f650c7c7
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Builder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+/**
+ * @author anttil
+ */
+public interface Builder<T>
+{
+    public T build();
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
new file mode 100644
index 00000000000..e16241275ed
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Experiment.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
+import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
+
+/**
+ * @author anttil
+ */
+public class Experiment implements EntityType, Browsable
+{
+    private ExperimentType type;
+
+    private final String code;
+
+    private Project project;
+
+    Experiment(ExperimentType type, String code, Project project)
+    {
+        this.type = type;
+        this.code = code;
+        this.project = project;
+    }
+
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
+    {
+        return code.equalsIgnoreCase(row.get("Code"));
+    }
+
+    @Override
+    public String getCode()
+    {
+        return code;
+    }
+
+    public ExperimentType getType()
+    {
+        return type;
+    }
+
+    public Project getProject()
+    {
+        return project;
+    }
+
+    void setType(ExperimentType type)
+    {
+        this.type = type;
+    }
+
+    void setProject(Project project)
+    {
+        this.project = project;
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleDialog.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
similarity index 80%
rename from ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleDialog.java
rename to ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
index 857f5f5bb04..6b1525a2555 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/page/dialog/AddSampleDialog.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/ExperimentType.java
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.uitest.page.dialog;
+package ch.systemsx.cisd.openbis.uitest.type;
 
-import ch.systemsx.cisd.openbis.uitest.page.Page;
-
-
-public class AddSampleDialog extends Page
+/**
+ * 
+ *
+ * @author anttil
+ */
+public class ExperimentType
 {
+
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
new file mode 100644
index 00000000000..4115f6737ad
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Project.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
+
+/**
+ * @author anttil
+ */
+public class Project implements Browsable
+{
+    private final String code;
+
+    private Space space;
+
+    private String description;
+
+    Project(String code, Space space, String description)
+    {
+        this.code = code;
+        this.space = space;
+        this.description = description;
+    }
+
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
+    {
+        return this.code.equalsIgnoreCase(row.get("Code"));
+    }
+
+    public String getCode()
+    {
+        return code;
+    }
+
+    public Space getSpace()
+    {
+        return space;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    void setSpace(Space space)
+    {
+        this.space = space;
+    }
+
+    void setDescription(String description)
+    {
+        this.description = description;
+    }
+
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
index 94be771826f..629ceecc5b2 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyType.java
@@ -17,7 +17,6 @@
 package ch.systemsx.cisd.openbis.uitest.type;
 
 import java.util.Map;
-import java.util.UUID;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 
@@ -27,7 +26,7 @@ import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 public class PropertyType implements Browsable
 {
 
-    private String code;
+    private final String code;
 
     private String label;
 
@@ -37,31 +36,31 @@ public class PropertyType implements Browsable
 
     private Vocabulary vocabulary;
 
-    public PropertyType()
+    PropertyType(String code, String label, String description, PropertyTypeDataType dataType,
+            Vocabulary vocabulary)
     {
-        this.code = UUID.randomUUID().toString();
-        this.label = "label of " + this.code;
-        this.description = "description";
-        this.dataType = PropertyTypeDataType.BOOLEAN;
-        this.vocabulary = null;
+        this.code = code;
+        this.label = label;
+        this.description = description;
+        this.dataType = dataType;
+        this.vocabulary = vocabulary;
     }
 
-    public PropertyType(Vocabulary vocabulary)
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
     {
-        this();
-        this.dataType = PropertyTypeDataType.CONTROLLED_VOCABULARY;
-        this.vocabulary = vocabulary;
+        return this.code.equalsIgnoreCase(row.get("Code"));
     }
 
-    public String getCode()
+    @Override
+    public String toString()
     {
-        return code;
+        return "PropertyType " + this.code;
     }
 
-    public PropertyType setCode(String code)
+    public String getCode()
     {
-        this.code = code;
-        return this;
+        return code;
     }
 
     public String getLabel()
@@ -69,55 +68,39 @@ public class PropertyType implements Browsable
         return label;
     }
 
-    public PropertyType setLabel(String label)
-    {
-        this.label = label;
-        return this;
-    }
-
     public String getDescription()
     {
         return description;
     }
 
-    public PropertyType setDescription(String description)
-    {
-        this.description = description;
-        return this;
-    }
-
     public PropertyTypeDataType getDataType()
     {
         return dataType;
     }
 
-    public PropertyType setDataType(PropertyTypeDataType dataType)
+    public Vocabulary getVocabulary()
     {
-        this.dataType = dataType;
-        return this;
+        return vocabulary;
     }
 
-    public Vocabulary getVocabulary()
+    void setLabel(String label)
     {
-        return vocabulary;
+        this.label = label;
     }
 
-    public PropertyType setVocabulary(Vocabulary vocabulary)
+    void setDescription(String description)
     {
-        this.vocabulary = vocabulary;
-        return this;
+        this.description = description;
     }
 
-    @Override
-    public boolean isRepresentedBy(Map<String, String> row)
+    void setDataType(PropertyTypeDataType dataType)
     {
-        return this.code.equalsIgnoreCase(row.get("Code"));
+        this.dataType = dataType;
     }
 
-    @Override
-    public String toString()
+    void setVocabulary(Vocabulary vocabulary)
     {
-        return "PropertyType " + this.code;
+        this.vocabulary = vocabulary;
     }
 
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
index efa95335484..558d237154f 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignment.java
@@ -27,14 +27,21 @@ import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 public class PropertyTypeAssignment implements Browsable
 {
 
-    private final PropertyType propertyType;
+    private PropertyType propertyType;
 
-    private final EntityType entityType;
+    private EntityType entityType;
 
-    public PropertyTypeAssignment(PropertyType propertyType, EntityType entityType)
+    private boolean mandatory;
+
+    private String initialValue;
+
+    public PropertyTypeAssignment(PropertyType propertyType, EntityType entityType,
+            boolean mandatory, String initialValue)
     {
         this.entityType = entityType;
         this.propertyType = propertyType;
+        this.mandatory = mandatory;
+        this.initialValue = initialValue;
     }
 
     @Override
@@ -50,4 +57,24 @@ public class PropertyTypeAssignment implements Browsable
     {
         return "PropertyTypeAssignment [" + this.propertyType + ", " + this.entityType + "]";
     }
+
+    public PropertyType getPropertyType()
+    {
+        return propertyType;
+    }
+
+    public EntityType getSampleType()
+    {
+        return entityType;
+    }
+
+    public boolean isMandatory()
+    {
+        return mandatory;
+    }
+
+    public String getInitialValue()
+    {
+        return initialValue;
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
new file mode 100644
index 00000000000..1942e93a1ad
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeAssignmentBuilder.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class PropertyTypeAssignmentBuilder implements Builder<PropertyTypeAssignment>
+{
+
+    private ApplicationRunner openbis;
+
+    private PropertyType propertyType;
+
+    private SampleType entityType;
+
+    private boolean mandatory;
+
+    private String initialValue;
+
+    public PropertyTypeAssignmentBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.propertyType = null;
+        this.entityType = null;
+        this.mandatory = false;
+        this.initialValue = "";
+    }
+
+    public PropertyTypeAssignmentBuilder withSampleType(SampleType sampleType)
+    {
+        this.entityType = sampleType;
+        return this;
+    }
+
+    public PropertyTypeAssignmentBuilder thatIsMandatory()
+    {
+        this.mandatory = true;
+        return this;
+    }
+
+    public PropertyTypeAssignmentBuilder havingInitialValueOf(String value)
+    {
+        this.initialValue = value;
+        return this;
+    }
+
+    @Override
+    public PropertyTypeAssignment build()
+    {
+        if (propertyType == null)
+        {
+            propertyType = new PropertyTypeBuilder(openbis).build();
+        }
+
+        if (entityType == null)
+        {
+            entityType = new SampleTypeBuilder(openbis).build();
+        }
+
+        return openbis.create(new PropertyTypeAssignment(propertyType, entityType, mandatory,
+                initialValue));
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
new file mode 100644
index 00000000000..14c3ac93ede
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/PropertyTypeBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.UUID;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class PropertyTypeBuilder implements Builder<PropertyType>
+{
+
+    private ApplicationRunner openbis;
+
+    private String code;
+
+    private String label;
+
+    private String description;
+
+    private PropertyTypeDataType dataType;
+
+    private Vocabulary vocabulary;
+
+    public PropertyTypeBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.code = UUID.randomUUID().toString();
+        this.label = "label of " + code;
+        this.description = "description of " + code;
+        this.dataType = PropertyTypeDataType.INTEGER;
+        this.vocabulary = null;
+    }
+
+    public PropertyTypeBuilder withVocabulary(Vocabulary vocabulary)
+    {
+        this.dataType = PropertyTypeDataType.CONTROLLED_VOCABULARY;
+        this.vocabulary = vocabulary;
+        return this;
+    }
+
+    @Override
+    public PropertyType build()
+    {
+        return openbis.create(new PropertyType(code, label, description, dataType, vocabulary));
+    }
+
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
new file mode 100644
index 00000000000..5e8dd34f589
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Sample.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.Collection;
+import java.util.Map;
+
+import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
+import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
+
+/**
+ * @author anttil
+ */
+public class Sample implements EntityType, Browsable
+{
+
+    private SampleType type;
+
+    private final String code;
+
+    private Experiment experiment;
+
+    private Space space;
+
+    private Collection<Sample> parents;
+
+    private Map<String, Object> properties;
+
+    Sample(SampleType type, String code, Experiment experiment, Space space,
+            Collection<Sample> parents, Map<String, Object> properties)
+    {
+        this.type = type;
+        this.code = code;
+        this.experiment = experiment;
+        this.space = space;
+        this.parents = parents;
+        this.properties = properties;
+    }
+
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
+    {
+        return code.equalsIgnoreCase(row.get("Code"));
+    }
+
+    @Override
+    public String getCode()
+    {
+        return code;
+    }
+
+    public SampleType getType()
+    {
+        return type;
+    }
+
+    public Experiment getExperiment()
+    {
+        return experiment;
+    }
+
+    public Space getSpace()
+    {
+        return space;
+    }
+
+    public Collection<Sample> getParents()
+    {
+        return parents;
+    }
+
+    public Map<String, Object> getProperties()
+    {
+        return properties;
+    }
+
+    void setType(SampleType type)
+    {
+        this.type = type;
+    }
+
+    void setExperiment(Experiment experiment)
+    {
+        this.experiment = experiment;
+    }
+
+    void setSpace(Space space)
+    {
+        this.space = space;
+    }
+
+    void setParents(Collection<Sample> parents)
+    {
+        this.parents = parents;
+    }
+
+    void setProperties(Map<String, Object> properties)
+    {
+        this.properties = properties;
+    }
+
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
new file mode 100644
index 00000000000..0fc623ea1cc
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class SampleBuilder implements Builder<Sample>
+{
+
+    private ApplicationRunner openbis;
+
+    private SampleType sampleType;
+
+    private String code;
+
+    private Experiment experiment;
+
+    private Space space;
+
+    private Collection<Sample> parents;
+
+    private Map<String, Object> properties;
+
+    public SampleBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.code = UUID.randomUUID().toString();
+        this.properties = new HashMap<String, Object>();
+        this.parents = new HashSet<Sample>();
+    }
+
+    @Override
+    public Sample build()
+    {
+        if (experiment != null)
+        {
+            space = experiment.getProject().getSpace();
+        } else if (space == null)
+        {
+            space = new SpaceBuilder(this.openbis).build();
+        }
+
+        if (sampleType == null)
+        {
+            sampleType = new SampleTypeBuilder(this.openbis).build();
+        }
+
+        for (PropertyTypeAssignment assignment : sampleType.getPropertyTypeAssignments())
+        {
+            if (assignment.isMandatory()
+                    && properties.get(assignment.getPropertyType().getLabel()) == null)
+            {
+                throw new IllegalStateException("missing property");
+            }
+        }
+
+        return openbis.create(new Sample(sampleType, code, experiment, space, parents, properties));
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
index 7016ae56769..27d437da3a9 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleType.java
@@ -16,8 +16,8 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
+import java.util.Collection;
 import java.util.Map;
-import java.util.UUID;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
@@ -28,12 +28,10 @@ import ch.systemsx.cisd.openbis.uitest.infra.EntityType;
 public class SampleType implements Browsable, EntityType
 {
 
-    private String code;
+    private final String code;
 
     private String description;
 
-    private String validationScript;
-
     private boolean listable;
 
     private boolean showContainer;
@@ -48,51 +46,46 @@ public class SampleType implements Browsable, EntityType
 
     private String generatedCodePrefix;
 
-    public SampleType()
-    {
-        this.code = UUID.randomUUID().toString();
-        this.description = "";
-        this.validationScript = "";
-        this.listable = true;
-        this.showContainer = false;
-        this.showParents = true;
-        this.uniqueSubcodes = false;
-        this.generateCodes = false;
-        this.showParentMetadata = false;
-        this.generatedCodePrefix = "S";
-    }
-
-    public String getCode()
-    {
-        return code;
-    }
+    private Collection<PropertyTypeAssignment> propertyTypeAssignments;
 
-    public SampleType setCode(String code)
+    SampleType(String code, String description, boolean listable, boolean showContainer,
+            boolean showParents, boolean uniqueSubcodes, boolean generateCodes,
+            boolean showParentMetadata, String generatedCodePrefix,
+            Collection<PropertyTypeAssignment> propertyTypeAssignments)
     {
         this.code = code;
-        return this;
+        this.description = description;
+        this.listable = listable;
+        this.showContainer = showContainer;
+        this.showParents = showParents;
+        this.uniqueSubcodes = uniqueSubcodes;
+        this.generateCodes = generateCodes;
+        this.showParentMetadata = showParentMetadata;
+        this.generatedCodePrefix = generatedCodePrefix;
+        this.propertyTypeAssignments = propertyTypeAssignments;
     }
 
-    public String getDescription()
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
     {
-        return description;
+        return this.code.equalsIgnoreCase(row.get("Code"));
     }
 
-    public SampleType setDescription(String description)
+    @Override
+    public String toString()
     {
-        this.description = description;
-        return this;
+        return "SampleType " + this.code;
     }
 
-    public String getValidationScript()
+    @Override
+    public String getCode()
     {
-        return validationScript;
+        return code;
     }
 
-    public SampleType setValidationScript(String validationScript)
+    public String getDescription()
     {
-        this.validationScript = validationScript;
-        return this;
+        return description;
     }
 
     public boolean isListable()
@@ -100,88 +93,83 @@ public class SampleType implements Browsable, EntityType
         return listable;
     }
 
-    public SampleType setListable(boolean listable)
+    public boolean isShowContainer()
     {
-        this.listable = listable;
-        return this;
+        return showContainer;
     }
 
-    public boolean isShowContainer()
+    public boolean isShowParents()
     {
-        return showContainer;
+        return showParents;
     }
 
-    public SampleType setShowContainer(boolean showContainer)
+    public boolean isUniqueSubcodes()
     {
-        this.showContainer = showContainer;
-        return this;
+        return uniqueSubcodes;
     }
 
-    public boolean isShowParents()
+    public boolean isGenerateCodes()
     {
-        return showParents;
+        return generateCodes;
     }
 
-    public SampleType setShowParents(boolean showParents)
+    public boolean isShowParentMetadata()
     {
-        this.showParents = showParents;
-        return this;
+        return showParentMetadata;
     }
 
-    public boolean isUniqueSubcodes()
+    public String getGeneratedCodePrefix()
     {
-        return uniqueSubcodes;
+        return generatedCodePrefix;
     }
 
-    public SampleType setUniqueSubcodes(boolean uniqueSubcodes)
+    public Collection<PropertyTypeAssignment> getPropertyTypeAssignments()
     {
-        this.uniqueSubcodes = uniqueSubcodes;
-        return this;
+        return propertyTypeAssignments;
     }
 
-    public boolean isGenerateCodes()
+    void setDescription(String description)
     {
-        return generateCodes;
+        this.description = description;
     }
 
-    public SampleType setGenerateCodes(boolean generateCodes)
+    void setListable(boolean listable)
     {
-        this.generateCodes = generateCodes;
-        return this;
+        this.listable = listable;
     }
 
-    public boolean isShowParentMetadata()
+    void setShowContainer(boolean showContainer)
     {
-        return showParentMetadata;
+        this.showContainer = showContainer;
     }
 
-    public SampleType setShowParentMetadata(boolean showParentMetadata)
+    void setShowParents(boolean showParents)
     {
-        this.showParentMetadata = showParentMetadata;
-        return this;
+        this.showParents = showParents;
     }
 
-    public String getGeneratedCodePrefix()
+    void setUniqueSubcodes(boolean uniqueSubcodes)
     {
-        return generatedCodePrefix;
+        this.uniqueSubcodes = uniqueSubcodes;
     }
 
-    public SampleType setGeneratedCodePrefix(String generatedCodePrefix)
+    void setGenerateCodes(boolean generateCodes)
     {
-        this.generatedCodePrefix = generatedCodePrefix;
-        return this;
+        this.generateCodes = generateCodes;
     }
 
-    @Override
-    public boolean isRepresentedBy(Map<String, String> row)
+    void setShowParentMetadata(boolean showParentMetadata)
     {
-        return this.code.equalsIgnoreCase(row.get("Code"));
+        this.showParentMetadata = showParentMetadata;
     }
 
-    @Override
-    public String toString()
+    void setGeneratedCodePrefix(String generatedCodePrefix)
     {
-        return "SampleType " + this.code;
+        this.generatedCodePrefix = generatedCodePrefix;
     }
 
+    void setPropertyTypeAssignments(Collection<PropertyTypeAssignment> propertyTypeAssignments)
+    {
+        this.propertyTypeAssignments = propertyTypeAssignments;
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
new file mode 100644
index 00000000000..cdc37fd1c3a
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeBuilder.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.UUID;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class SampleTypeBuilder implements Builder<SampleType>
+{
+
+    private ApplicationRunner openbis;
+
+    private String code;
+
+    private String description;
+
+    private boolean listable;
+
+    private boolean showsContainer;
+
+    private boolean showsParents;
+
+    private boolean hasUniqueSubcodes;
+
+    private boolean generatesCodes;
+
+    private boolean showsParentMetadata;
+
+    private String generatedCodePrefix;
+
+    private Collection<PropertyTypeAssignment> propertyTypeAssignments;
+
+    public SampleTypeBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.code = UUID.randomUUID().toString();
+        this.description = "";
+        this.listable = true;
+        this.showsContainer = false;
+        this.showsParents = true;
+        this.hasUniqueSubcodes = false;
+        this.generatesCodes = false;
+        this.showsParentMetadata = false;
+        this.generatedCodePrefix = "S";
+        this.propertyTypeAssignments = new HashSet<PropertyTypeAssignment>();
+    }
+
+    public SampleTypeBuilder thatIsListable()
+    {
+        this.listable = true;
+        return this;
+    }
+
+    public SampleTypeBuilder thatIsNotListable()
+    {
+        this.listable = false;
+        return this;
+    }
+
+    public SampleTypeBuilder withCode(String code)
+    {
+        this.code = code;
+        return this;
+    }
+
+    @Override
+    public SampleType build()
+    {
+        return openbis.create(new SampleType(code, description, listable, showsContainer,
+                showsParents,
+                hasUniqueSubcodes, generatesCodes, showsParentMetadata, generatedCodePrefix,
+                propertyTypeAssignments));
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeUpdateBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeUpdateBuilder.java
new file mode 100644
index 00000000000..fd5db460f9c
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SampleTypeUpdateBuilder.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class SampleTypeUpdateBuilder implements UpdateBuilder
+{
+
+    private ApplicationRunner openbis;
+
+    private SampleType type;
+
+    public SampleTypeUpdateBuilder(ApplicationRunner openbis, SampleType type)
+    {
+        this.openbis = openbis;
+        this.type = type;
+    }
+
+    public SampleTypeUpdateBuilder settingItListable()
+    {
+        type.setListable(true);
+        return this;
+    }
+
+    public SampleTypeUpdateBuilder settingItNonListable()
+    {
+        type.setListable(false);
+        return this;
+    }
+
+    @Override
+    public void update()
+    {
+        openbis.update(type);
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
index c7c5c337008..7147b89d8f6 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Space.java
@@ -17,7 +17,6 @@
 package ch.systemsx.cisd.openbis.uitest.type;
 
 import java.util.Map;
-import java.util.UUID;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 
@@ -26,37 +25,14 @@ import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
  */
 public class Space implements Browsable
 {
-
-    private String code;
+    private final String code;
 
     private String description;
 
-    public Space()
-    {
-        this.code = UUID.randomUUID().toString();
-        this.description = "";
-    }
-
-    public String getCode()
-    {
-        return code;
-    }
-
-    public Space setCode(String code)
+    Space(String code, String description)
     {
         this.code = code;
-        return this;
-    }
-
-    public String getDescription()
-    {
-        return description;
-    }
-
-    public Space setDescription(String description)
-    {
         this.description = description;
-        return this;
     }
 
     @Override
@@ -71,4 +47,18 @@ public class Space implements Browsable
         return "Space " + this.code;
     }
 
+    public String getCode()
+    {
+        return code;
+    }
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+    void setDescription(String description)
+    {
+        this.description = description;
+    }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
new file mode 100644
index 00000000000..a499be83d44
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/SpaceBuilder.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.UUID;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class SpaceBuilder implements Builder<Space>
+{
+
+    private ApplicationRunner openbis;
+
+    private final String code;
+
+    private final String description;
+
+    public SpaceBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.code = UUID.randomUUID().toString();
+        this.description = "";
+    }
+
+    @Override
+    public Space build()
+    {
+        return openbis.create(new Space(code, description));
+    }
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/UpdateBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/UpdateBuilder.java
new file mode 100644
index 00000000000..163c773ec60
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/UpdateBuilder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+/**
+ * @author anttil
+ */
+public interface UpdateBuilder
+{
+    public void update();
+}
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
index 06a3c498f77..86909cd8ad8 100644
--- a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/Vocabulary.java
@@ -16,10 +16,8 @@
 
 package ch.systemsx.cisd.openbis.uitest.type;
 
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
 
@@ -28,8 +26,7 @@ import ch.systemsx.cisd.openbis.uitest.infra.Browsable;
  */
 public class Vocabulary implements Browsable
 {
-
-    private String code;
+    private final String code;
 
     private String description;
 
@@ -37,35 +34,34 @@ public class Vocabulary implements Browsable
 
     private String url;
 
-    public Vocabulary()
+    Vocabulary(String code, String description, Set<String> terms, String url)
     {
-        this.code = UUID.randomUUID().toString();
-        this.description = "";
-        this.terms = new HashSet<String>();
-        this.terms.add("term1");
-        this.url = "http://invalid.com/${term}";
+        this.code = code;
+        this.description = description;
+        this.terms = terms;
+        this.url = url;
     }
 
-    public String getCode()
+    @Override
+    public boolean isRepresentedBy(Map<String, String> row)
     {
-        return code;
+        return this.code.equalsIgnoreCase(row.get("Code"));
     }
 
-    public Vocabulary setCode(String code)
+    @Override
+    public String toString()
     {
-        this.code = code;
-        return this;
+        return "Vocabulary " + this.code + ": " + this.terms;
     }
 
-    public String getDescription()
+    public String getCode()
     {
-        return description;
+        return code;
     }
 
-    public Vocabulary setDescription(String description)
+    public String getDescription()
     {
-        this.description = description;
-        return this;
+        return description;
     }
 
     public Set<String> getTerms()
@@ -73,32 +69,23 @@ public class Vocabulary implements Browsable
         return terms;
     }
 
-    public Vocabulary setTerms(Set<String> terms)
-    {
-        this.terms = terms;
-        return this;
-    }
-
     public String getUrl()
     {
         return url;
     }
 
-    public Vocabulary setUrl(String url)
+    void setDescription(String description)
     {
-        this.url = url;
-        return this;
+        this.description = description;
     }
 
-    @Override
-    public boolean isRepresentedBy(Map<String, String> row)
+    void setTerms(Set<String> terms)
     {
-        return this.code.equalsIgnoreCase(row.get("Code"));
+        this.terms = terms;
     }
 
-    @Override
-    public String toString()
+    void setUrl(String url)
     {
-        return "Vocabulary " + this.code + ": " + this.terms;
+        this.url = url;
     }
 }
diff --git a/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java
new file mode 100644
index 00000000000..13de497bb9d
--- /dev/null
+++ b/ui-test/source/java/ch/systemsx/cisd/openbis/uitest/type/VocabularyBuilder.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.uitest.type;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import ch.systemsx.cisd.openbis.uitest.infra.ApplicationRunner;
+
+/**
+ * @author anttil
+ */
+public class VocabularyBuilder implements Builder<Vocabulary>
+{
+
+    private ApplicationRunner openbis;
+
+    private String code;
+
+    private String description;
+
+    private Set<String> terms;
+
+    private String url;
+
+    public VocabularyBuilder(ApplicationRunner openbis)
+    {
+        this.openbis = openbis;
+        this.code = UUID.randomUUID().toString();
+        this.description = "";
+        this.terms = new HashSet<String>();
+        this.terms.add("term1");
+        this.url = "http://test.com/${term}";
+    }
+
+    @Override
+    public Vocabulary build()
+    {
+        return openbis.create(new Vocabulary(code, description, terms, url));
+    }
+
+}
-- 
GitLab