diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java
index 072b3a065ea0d8015c00227d191147813e71c06b..2a7a0e280720a0bfd31e8b3218f50c7ef211a1b0 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/SearchService.java
@@ -30,6 +30,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IExperimentIm
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IMaterialImmutable;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.ISampleImmutable;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.ISearchService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IVocabularyImmutable;
 import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.MaterialIdentifierCollection;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchCriteria;
@@ -42,6 +43,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 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.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory;
 
@@ -206,4 +208,10 @@ public class SearchService implements ISearchService
         return result;
     }
 
+    @Override
+    public IVocabularyImmutable searchForVocabulary(String code)
+    {
+        Vocabulary vocabulary = openBisService.tryGetVocabulary(code);
+        return new VocabularyImmutable(vocabulary);
+    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bbe360039bb434ccc05232ae7e67ca0c2bcdad2
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyImmutable.java
@@ -0,0 +1,90 @@
+/*
+ * 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.etlserver.registrator.api.v1.impl;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IVocabularyImmutable;
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IVocabularyTermImmutable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Vocabulary;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
+
+/**
+ * 
+ *
+ * @author Jakub Straszewski
+ */
+public class VocabularyImmutable implements IVocabularyImmutable
+{
+    private final Vocabulary vocabulary;
+
+    public VocabularyImmutable(Vocabulary vocabulary)
+    {
+        this.vocabulary = vocabulary;
+    }
+
+    @Override
+    public String getCode()
+    {
+        return vocabulary.getCode();
+    }
+
+    @Override
+    public String getDescription()
+    {
+        return vocabulary.getDescription();
+    }
+
+    @Override
+    public boolean isManagedInternally()
+    {
+        return vocabulary.isManagedInternally();
+    }
+
+    @Override
+    public boolean isInternalNamespace()
+    {
+        return vocabulary.isInternalNamespace();
+    }
+
+    @Override
+    public boolean isChosenFromList()
+    {
+        return vocabulary.isChosenFromList();
+    }
+
+    @Override
+    public String getUrlTemplate()
+    {
+        return vocabulary.getURLTemplate();
+    }
+
+    @Override
+    public List<IVocabularyTermImmutable> getTerms()
+    {
+        List<IVocabularyTermImmutable> results = new LinkedList<IVocabularyTermImmutable>();
+
+        for (VocabularyTerm term : vocabulary.getTerms())
+        {
+            results.add(new VocabularyTermImmutable(term));
+        }
+
+        return results;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyTermImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyTermImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..112b5a087a4c516652769a98c8d35544c1cca355
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/registrator/api/v1/impl/VocabularyTermImmutable.java
@@ -0,0 +1,63 @@
+/*
+ * 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.etlserver.registrator.api.v1.impl;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1.IVocabularyTermImmutable;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
+
+/**
+ * @author Jakub Straszewski
+ */
+public class VocabularyTermImmutable implements IVocabularyTermImmutable
+{
+    private final VocabularyTerm vocabularyTerm;
+
+    public VocabularyTermImmutable(VocabularyTerm vocabularyTerm)
+    {
+        this.vocabularyTerm = vocabularyTerm;
+    }
+
+    @Override
+    public String getCode()
+    {
+        return vocabularyTerm.getCode();
+    }
+
+    @Override
+    public String getDescription()
+    {
+        return vocabularyTerm.getDescription();
+    }
+
+    @Override
+    public String getLabel()
+    {
+        return vocabularyTerm.getLabel();
+    }
+
+    @Override
+    public String getUrl()
+    {
+        return vocabularyTerm.getUrl();
+    }
+
+    @Override
+    public Long getOrdinal()
+    {
+        return vocabularyTerm.getOrdinal();
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
index aaa4440c848f6bea758991ae8e7ad384aa8e1081..2ff59c99040f4dbd322750024ba044699bf909c3 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/EncapsulatedOpenBISService.java
@@ -64,6 +64,7 @@ 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.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+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.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -240,6 +241,12 @@ public final class EncapsulatedOpenBISService implements IEncapsulatedOpenBISSer
         return service.listVocabularyTerms(session.getSessionToken(), vocabularyCode);
     }
 
+    @Override
+    public Vocabulary tryGetVocabulary(String code)
+    {
+        return service.tryGetVocabulary(session.getSessionToken(), code);
+    }
+
     @Override
     public SampleType getSampleType(String sampleTypeCode) throws UserFailureException
     {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
index 3278b66ecd24d0a606cd0c6fb6ee4b7bb6d29380..798cd88f6a2de869c220eed2888893cea3fc88c4 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/IEncapsulatedOpenBISService.java
@@ -51,6 +51,7 @@ 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.Space;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+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.dto.AtomicEntityOperationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.dto.AtomicEntityOperationResult;
@@ -193,6 +194,12 @@ public interface IEncapsulatedOpenBISService
     public Collection<VocabularyTerm> listVocabularyTerms(String vocabularyCode)
             throws UserFailureException;
 
+    /**
+     * Returns a vocabulary with given code
+     */
+    @ManagedAuthentication
+    public Vocabulary tryGetVocabulary(String code);
+
     /**
      * Gets the experiment type with assigned property types for the specified experiment type code.
      */
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java
index 4689d760a220c148aed15f0f9ba8f90df45bbf5f..bf9d7dc41b9be54e94f7d13be64f86e4cf20ffc4 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/ISearchService.java
@@ -102,4 +102,9 @@ public interface ISearchService
      * @return a list of materials matching the specified collection.
      */
     public List<IMaterialImmutable> listMaterials(MaterialIdentifierCollection identifierCollection);
+
+    /**
+     * @return a controlled vocabulary with the given code.
+     */
+    public IVocabularyImmutable searchForVocabulary(String code);
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0aa73c9d232ebc9a17bd06ae6513d2f27adfab1
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyImmutable.java
@@ -0,0 +1,62 @@
+/*
+ * 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.dss.generic.shared.api.internal.v1;
+
+import java.util.List;
+
+/**
+ * Read-only interface to a vocabulary.
+ *
+ * @author Jakub Straszewski
+ */
+public interface IVocabularyImmutable
+{
+
+    /**
+     * Returns the vocabulary code.
+     */
+    public String getCode();
+
+    /**
+     * Returns the vocabulary description.
+     */
+    public String getDescription();
+
+    /**
+     * Return <code>true</code> if the vocabulary is managed internally in openBIS.
+     */
+    boolean isManagedInternally();
+
+    /**
+     * Return <code>true</code> if the vocabulary is in the internal openBIS namespace.
+     */
+    boolean isInternalNamespace();
+
+    boolean isChosenFromList();
+
+    /**
+     * Returns a URL template (e.g a search query) that can display additional information for the
+     * concrete vocabulary terms. Can return null.
+     */
+    String getUrlTemplate();
+
+    /**
+     * Return a list with all terms within the vocabulary.
+     */
+    List<IVocabularyTermImmutable> getTerms();
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyTermImmutable.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyTermImmutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7aff48fbd33655364b70f489cfac0d09bc2f409
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/api/internal/v1/IVocabularyTermImmutable.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1;
+
+/**
+ * Read-only interface to an existing vocabulary term.
+ * 
+ * @author Jakub Straszewski
+ */
+public interface IVocabularyTermImmutable
+{
+    /**
+     * Return the term's code.
+     */
+    String getCode();
+
+    /**
+     * Return the term's description.
+     */
+    String getDescription();
+
+    /**
+     * Return the term's label.
+     */
+    String getLabel();
+
+    /**
+     * Return an associated URL specifying additional information for the vocabulary term.
+     */
+    String getUrl();
+
+    /**
+     * Return the position of the term in the context of a vocabulary.
+     */
+    Long getOrdinal();
+
+}
+
diff --git a/datastore_server/sourceTest/core-plugins/generic-test/1/dss/drop-boxes/rich-test/rich-data-set-handler.py b/datastore_server/sourceTest/core-plugins/generic-test/1/dss/drop-boxes/rich-test/rich-data-set-handler.py
index 2bdfdd46e3b839665ac1092f39c002c32c68e2c4..e22608586530eb0123ccaf88d61e6963b716599d 100644
--- a/datastore_server/sourceTest/core-plugins/generic-test/1/dss/drop-boxes/rich-test/rich-data-set-handler.py
+++ b/datastore_server/sourceTest/core-plugins/generic-test/1/dss/drop-boxes/rich-test/rich-data-set-handler.py
@@ -55,6 +55,13 @@ def updateExperiment(transaction):
     ex = transaction.getExperimentForUpdate("/CISD/NEMO/EXP1")
     ex.setPropertyValue("DESCRIPTION", "modified experiment description")
 
+def createBacterias(transaction):
+    vocabulary = transaction.getSearchService().searchForVocabulary("ORGANISM")
+    for term in vocabulary.getTerms():
+        mat = transaction.createNewMaterial("BC_%s" % term.getCode(), "BACTERIUM")
+        mat.setPropertyValue("DESCRIPTION", term.getDescription())
+        mat.setPropertyValue("ORGANISM", term.getCode())
+        
 def process(transaction):
     # create experiment
     experiment = create_experiment_if_needed(transaction)
@@ -76,5 +83,8 @@ def process(transaction):
 
     # register samples
     createSamples(transaction)
-
+    
+    # read controlled vocabularies and create materials
+    createBacterias(transaction)
+    
     transaction.getRegistrationContext().getPersistentMap().put("email_text", "rich_email_text")
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/FeatureRichDataSetImportSystemTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/FeatureRichDataSetImportSystemTest.java
index 3929acb2a5d9c8a5d097fd549e84daf56826c0d6..9b067dd7b46d679b9ac177efebdfdeacc20faf64 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/FeatureRichDataSetImportSystemTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/datastoreserver/systemtests/FeatureRichDataSetImportSystemTest.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.datastoreserver.systemtests;
 
 import java.io.File;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -80,6 +81,8 @@ public class FeatureRichDataSetImportSystemTest extends SystemTestCase
         assertMaterialUpdated(openBISService);
 
         assertExperimentUpdated(openBISService);
+
+        assertVocabularyMaterialsCreated(openBISService);
     }
 
     private void assertExperimentUpdated(IEncapsulatedOpenBISService openBISService)
@@ -164,6 +167,47 @@ public class FeatureRichDataSetImportSystemTest extends SystemTestCase
 
     }
 
+    private void assertVocabularyMaterialsCreated(IEncapsulatedOpenBISService openBISService)
+    {
+        String[] items = new String[]
+            { "RAT", "DOG", "HUMAN", "GORILLA", "FLY" };
+        
+        LinkedList<MaterialIdentifier> ids = new LinkedList<MaterialIdentifier>();
+
+        for (String item : items)
+        {
+            MaterialIdentifier ident = new MaterialIdentifier("BC_" + item, "BACTERIUM");
+            ids.add(ident);
+        }
+
+        ListMaterialCriteria criteria = ListMaterialCriteria.createFromMaterialIdentifiers(ids);
+        List<Material> materials = openBISService.listMaterials(criteria, true);
+
+        assertEquals(items.length, materials.size());
+
+        for (Material m : materials)
+        {
+            String code = m.getCode();
+            
+            HashMap<String , IEntityProperty> properties = new HashMap<String , IEntityProperty>();
+            
+            for (IEntityProperty property : m.getProperties())
+            {
+                properties.put(property.getPropertyType().getCode(), property);
+            }
+
+            IEntityProperty descriptionProperty = properties.get("DESCRIPTION");
+            IEntityProperty organismProperty = properties.get("ORGANISM");
+
+            assertNotNull(descriptionProperty);
+            assertEquals(code.substring(3), organismProperty.getVocabularyTerm().getCode());
+
+            assertEquals(descriptionProperty.getValue(), organismProperty.getVocabularyTerm()
+                    .getDescription());
+
+        }
+    }
+
     private void assertMaterialUpdated(IEncapsulatedOpenBISService openBISService)
     {
         LinkedList<MaterialIdentifier> ids = new LinkedList<MaterialIdentifier>();