diff --git a/openbis/diffCurrentAndPreviousMigrations.sh b/openbis/diffCurrentAndPreviousMigrations.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5d5075125afa4e4e4f1da15a4b5d2f19095f36e0
--- /dev/null
+++ b/openbis/diffCurrentAndPreviousMigrations.sh
@@ -0,0 +1,29 @@
+#!/opt/local/bin/ruby
+
+versions = `ls source/sql/postgresql`.map { |dir| dir.to_i }
+@curr = versions.max
+@prev = @curr - 1
+
+@curr = "%03d" % @curr
+@prev = "%03d" % @prev
+
+puts "Will check the diff beetween versions #{@prev} and #{@curr}"
+
+def copyDir(dir)
+  files = Dir[dir].map {|f| File.expand_path f }
+  files.each do |f|
+    new_f = f.gsub(@prev, @curr)
+     diff_files = " #{f} #{new_f}"
+     system("git diff --no-index" + diff_files)  
+  end
+end
+
+copyDir("source/sql/postgresql/#{@prev}/*")
+copyDir("source/sql/generic/#{@prev}/*")
+copyDir("sourceTest/sql/postgresql/#{@prev}/*")
+
+
+
+
+
+
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 862f91bb75d6d486064c434387a2a8831d921d87..3fe417cc6172bd01de3bbe0707ffdbe50f70ecfe 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -2564,4 +2564,12 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         List<DataStorePE> dataStorePEs = dataStoreDAO.listDataStores();
         return DataStoreTranslator.translate(dataStorePEs);
     }
+
+    public List<Material> searchForMaterials(String sessionToken, DetailedSearchCriteria criteria)
+    {
+        final Session session = getSession(sessionToken);
+        SearchHelper searchHelper =
+                new SearchHelper(session, businessObjectFactory, getDAOFactory());
+        return searchHelper.searchForMaterials(criteria);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index a62f49afe033109082ad517be21d1c3386dd5452..52a0cecd784af8b3119725edf485fa10c73ea7ce 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -1185,4 +1185,10 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
+    public List<Material> searchForMaterials(String sessionToken, DetailedSearchCriteria criteria)
+    {
+        logAccess(sessionToken, "search_for_materials", "criteria(%s)", criteria);
+        return null;
+    }
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SearchHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SearchHelper.java
index 4ba156110c947ea6c4f7f1aba3bdc17a525d9b06..3626384bf466a5e68672c9a4e0cea3c8ed75265b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SearchHelper.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SearchHelper.java
@@ -20,13 +20,16 @@ import java.util.List;
 
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.datasetlister.IDatasetLister;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister;
 import ch.systemsx.cisd.openbis.generic.server.business.search.DataSetSearchManager;
+import ch.systemsx.cisd.openbis.generic.server.business.search.MaterialSearchManager;
 import ch.systemsx.cisd.openbis.generic.server.business.search.SampleSearchManager;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 
@@ -66,4 +69,12 @@ class SearchHelper
         return new DataSetSearchManager(searchDAO, dataSetLister)
                 .searchForDataSets(detailedSearchCriteria);
     }
+
+    public List<Material> searchForMaterials(DetailedSearchCriteria detailedSearchCriteria)
+    {
+        IHibernateSearchDAO searchDAO = daoFactory.getHibernateSearchDAO();
+        IMaterialLister materialLister = businessObjectFactory.createMaterialLister(session);
+        return new MaterialSearchManager(searchDAO, materialLister)
+                .searchForMaterials(detailedSearchCriteria);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
index fdb0fd5ab5a91ca960ddee8383d0a8307d0dd622..2c9285ab1cda1a986a8cc9225b3eed75e93d55a8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationService.java
@@ -32,6 +32,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
 import ch.systemsx.cisd.authentication.ISessionManager;
+import ch.systemsx.cisd.common.exceptions.NotImplementedException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.server.AbstractServer;
@@ -51,6 +52,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOptions;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
@@ -664,4 +667,26 @@ public class GeneralInformationService extends AbstractServer<IGeneralInformatio
         return Translator.translateProjects(commonServer.listProjects(sessionToken));
     }
 
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @Capability("GET_MATERIALS_BY_CODES")
+    public List<Material> getMaterialByCodes(String sessionToken,
+            List<MaterialIdentifier> materialIdentifier)
+    {
+        throw new NotImplementedException();
+        // TODO Auto-generated method stub
+    }
+
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    @Capability("SEARCH_FOR_MATERIALS")
+    public List<Material> searchForMaterials(String sessionToken, SearchCriteria searchCriteria)
+    {
+        DetailedSearchCriteria detailedSearchCriteria =
+                SearchCriteriaToDetailedSearchCriteriaTranslator.convert(
+                        SearchableEntityKind.MATERIAL, searchCriteria);
+        List<ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material> materials =
+                commonServer.searchForMaterials(sessionToken, detailedSearchCriteria);
+        return Translator.translateMaterials(materials);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
index 575111a2ac7da610e2d3980ac940b35376132b8d..b999197d8334d4b4ccfde49af50a83f801572f94 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/GeneralInformationServiceLogger.java
@@ -32,6 +32,8 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSet.Connections;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
@@ -214,4 +216,19 @@ class GeneralInformationServiceLogger extends AbstractServerLogger implements
                 "EXPERIMENTS(%s) CONNECTIONS(%s)", abbreviate(experiments), connectionsToGet);
         return null;
     }
+
+    public List<Material> getMaterialByCodes(String sessionToken,
+            List<MaterialIdentifier> materialIdentifier)
+    {
+        logAccess(sessionToken, "get-material-by-codes", "MATERIAL_IDENTIFIERS(%s)",
+                abbreviate(materialIdentifier));
+
+        return null;
+    }
+
+    public List<Material> searchForMaterials(String sessionToken, SearchCriteria searchCriteria)
+    {
+        logAccess(sessionToken, "search-for-materials", "SEARCH_CRITERIA(%s)", searchCriteria);
+        return null;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
index 2a7acf1b22d83f28298e0948a2e0be3a7ff9bc36..1c5b222631b18a12ea04897becf5c0764d8e8305 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/SearchCriteriaToDetailedSearchCriteriaTranslator.java
@@ -37,6 +37,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchField;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchSubCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IAttributeSearchFieldKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleAttributeSearchFieldKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SearchCriteriaConnection;
 
@@ -67,6 +68,7 @@ public class SearchCriteriaToDetailedSearchCriteriaTranslator
         translators.put(SearchableEntityKind.SAMPLE_PARENT, new SampleAttributeTranslator());
         translators.put(SearchableEntityKind.SAMPLE_CHILD, new SampleAttributeTranslator());
         translators.put(SearchableEntityKind.SAMPLE_CONTAINER, new SampleAttributeTranslator());
+        translators.put(SearchableEntityKind.MATERIAL, new MaterialAttributeTranslator());
     }
 
     private static IMatchClauseAttributeTranslator translatorFor(SearchableEntityKind entityKind)
@@ -104,6 +106,8 @@ public class SearchCriteriaToDetailedSearchCriteriaTranslator
                 return AssociatedEntityKind.SAMPLE_PARENT;
             case SAMPLE_CHILD:
                 return AssociatedEntityKind.SAMPLE_CHILD;
+            case MATERIAL:
+                return AssociatedEntityKind.MATERIAL;
         }
         return null; // can't happen
     }
@@ -179,13 +183,34 @@ public class SearchCriteriaToDetailedSearchCriteriaTranslator
                     ans = ExperimentAttributeSearchFieldKind.PROJECT;
                     break;
                 default:
-                    throwInvalidSearchAttributeException(attribute, SearchableEntityKind.SAMPLE);
+                    throwInvalidSearchAttributeException(attribute, SearchableEntityKind.EXPERIMENT);
             }
             return ans;
         }
 
     }
 
+    public static class MaterialAttributeTranslator implements IMatchClauseAttributeTranslator
+    {
+        public IAttributeSearchFieldKind convertMatchClauseAttributeToAttributeSearchFieldKind(
+                MatchClauseAttribute attribute)
+        {
+            IAttributeSearchFieldKind ans = null;
+            switch (attribute)
+            {
+                case CODE:
+                    ans = MaterialAttributeSearchFieldKind.CODE;
+                    break;
+                case TYPE:
+                    ans = MaterialAttributeSearchFieldKind.MATERIAL_TYPE;
+                    break;
+                default:
+                    throwInvalidSearchAttributeException(attribute, SearchableEntityKind.MATERIAL);
+            }
+            return ans;
+        }
+    }
+
     public static class DataSetAttributeTranslator implements IMatchClauseAttributeTranslator
     {
         public IAttributeSearchFieldKind convertMatchClauseAttributeToAttributeSearchFieldKind(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/MaterialSearchManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/MaterialSearchManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..d33510166d38d86ba869ea96a04acd434c8844b1
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/MaterialSearchManager.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.business.search;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.springframework.dao.DataAccessException;
+
+import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IHibernateSearchDAO;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchAssociationCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DetailedSearchCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
+
+/**
+ * @author jakubs
+ */
+public class MaterialSearchManager extends AbstractSearchManager<IMaterialLister>
+{
+
+    public MaterialSearchManager(IHibernateSearchDAO searchDAO, IMaterialLister lister)
+    {
+        super(searchDAO, lister);
+    }
+
+    public List<Material> searchForMaterials(DetailedSearchCriteria criteria)
+            throws DataAccessException
+    {
+        List<Long> materialIds =
+                searchDAO.searchForEntityIds(criteria,
+                        ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.MATERIAL,
+                        Collections.<DetailedSearchAssociationCriteria> emptyList());
+
+        return lister.list(new ListMaterialCriteria(materialIds), true);
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 8f3eeaabecd62ae1ab034602547a8b2e22d4375f..6d77f3bd6d07fb06dace6a524e3c68ea56862e8c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -1549,4 +1549,12 @@ public interface ICommonServer extends IServer
     public void deletePermanently(final String sessionToken,
             @AuthorizationGuard(guardClass = DeletionTechIdCollectionPredicate.class)
             final List<TechId> deletionIds, boolean force);
+
+    /**
+     * Performs an <i>Hibernate Search</i> based on given parameters.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleWithHierarchy.SPACE_OBSERVER)
+    public List<Material> searchForMaterials(String sessionToken, DetailedSearchCriteria criteria);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
index 602f303805deaae6528c41961e94a584733977a7..546738df236a73b6991bd185b39a603fce72f681 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/Translator.java
@@ -24,7 +24,9 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ControlledVocabularyPropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.ControlledVocabularyPropertyType.ControlledVocabularyPropertyTypeInitializer;
@@ -36,6 +38,9 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.DataSetType.DataSetTyp
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDetails;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment.ExperimentInitializer;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material.MaterialInitializer;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.MaterialTypeIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType.PropertyTypeInitializer;
@@ -56,6 +61,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleLevel;
+import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper;
 
 /**
  * @author Franz-Josef Elmer
@@ -129,7 +135,8 @@ public class Translator
             initializer.setExperimentIdentifierOrNull(experimentOrNull.getIdentifier());
         }
 
-        EntityRegistrationDetails registrationDetails = translateRegistrationDetailsWithModificationDate(privateSample);
+        EntityRegistrationDetails registrationDetails =
+                translateRegistrationDetailsWithModificationDate(privateSample);
         initializer.setRegistrationDetails(registrationDetails);
 
         return new Sample(initializer);
@@ -374,7 +381,8 @@ public class Translator
                     break;
             }
         }
-        EntityRegistrationDetails registrationDetails = translateRegistrationDetailsWithModificationDate(externalDatum);
+        EntityRegistrationDetails registrationDetails =
+                translateRegistrationDetailsWithModificationDate(externalDatum);
         initializer.setRegistrationDetails(registrationDetails);
 
         return new DataSet(initializer);
@@ -432,4 +440,71 @@ public class Translator
         initializer.setTerms(translate(privateVocabulary.getTerms()));
         return new Vocabulary(initializer);
     }
+
+    public static Material translate(
+            ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material,
+            Map<Long, Material> materialsCache)
+    {
+        MaterialInitializer mi = new MaterialInitializer();
+
+        mi.setMaterialCode(material.getCode());
+
+        MaterialTypeIdentifier typeIdentifier =
+                new MaterialTypeIdentifier(material.getMaterialType().getCode());
+
+        mi.setMaterialTypeIdentifier(typeIdentifier);
+
+        material.getProperties();
+
+        List<IEntityProperty> originalProperties = material.getProperties();
+        Map<String, String> properties = EntityHelper.convertToStringMap(originalProperties);
+        Map<String, Material> materialProperties =
+                convertMaterialProperties(originalProperties, materialsCache);
+
+        mi.setMaterialProperties(materialProperties);
+
+        mi.setProperties(properties);
+
+        mi.setRegistrationDetails(translateRegistrationDetails(material));
+
+        return new Material(mi);
+    }
+
+    private static Map<String, Material> convertMaterialProperties(
+            List<IEntityProperty> properties, Map<Long, Material> materialsCache)
+    {
+        HashMap<String, Material> result = new HashMap<String, Material>();
+        if (properties != null)
+        {
+            for (IEntityProperty property : properties)
+            {
+                ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material =
+                        property.getMaterial();
+                if (material != null)
+                {
+                    Material apiMaterial = materialsCache.get(material.getId());
+                    if (apiMaterial == null)
+                    {
+                        apiMaterial = translate(material, materialsCache);
+                        materialsCache.put(material.getId(), apiMaterial);
+                    }
+                    String propCode = property.getPropertyType().getCode();
+                    result.put(propCode, apiMaterial);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static List<Material> translateMaterials(
+            Collection<ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material> materials)
+    {
+        Map<Long, Material> materialsCache = new HashMap<Long, Material>();
+        List<Material> list = new LinkedList<Material>();
+        for (ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material material : materials)
+        {
+            list.add(translate(material, materialsCache));
+        }
+        return list;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AssociatedEntityKind.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AssociatedEntityKind.java
index 69c911eb6d9251805e8e537f33ddd6394855e20b..f2c98e2cc831b15aaba33e8fc6a8ad944ae977cd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AssociatedEntityKind.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AssociatedEntityKind.java
@@ -47,7 +47,9 @@ public enum AssociatedEntityKind implements Serializable
 
     SAMPLE_CHILD("Child", EntityKind.SAMPLE, EnumSet.of(EntityKind.SAMPLE)),
 
-    SAMPLE_PARENT("Parent", EntityKind.SAMPLE, EnumSet.of(EntityKind.SAMPLE));
+    SAMPLE_PARENT("Parent", EntityKind.SAMPLE, EnumSet.of(EntityKind.SAMPLE)),
+
+    MATERIAL("Material", EntityKind.MATERIAL, EnumSet.noneOf(EntityKind.class));
 
     private final String description;
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java
index d51441485ef52c242f5a7e67df97fd53373a1c80..3ba35f24da7bb0f45a8a83bea5c995bd91a79109 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityTypeDAOTest.java
@@ -129,15 +129,16 @@ public final class EntityTypeDAOTest extends AbstractDAOTest
 
     private PropertyTypePE createMaterialPropertyType(MaterialTypePE materialType)
     {
-        return createPropertyType(daoFactory.getPropertyTypeDAO().getDataTypeByCode(
-                DataTypeCode.MATERIAL), "USER.MATERIAL-PROPERTY-TYPE", null, materialType);
+        return createPropertyType(
+                daoFactory.getPropertyTypeDAO().getDataTypeByCode(DataTypeCode.MATERIAL),
+                "USER.MATERIAL-PROPERTY-TYPE", null, materialType);
     }
 
     @Test
     public final void testListMaterialTypes()
     {
         final IEntityTypeDAO entityTypeDAO = daoFactory.getEntityTypeDAO(EntityKind.MATERIAL);
-        assertEquals(7, entityTypeDAO.listEntityTypes().size());
+        assertEquals(8, entityTypeDAO.listEntityTypes().size());
     }
 
     @Test(dependsOnMethods = "testListMaterialTypes")
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index e4d3a521769f015a581c70c2df8b8577751bd5d9..98decaba952699dd983faccb12a1ae24ec922654 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -19,10 +19,12 @@ package ch.systemsx.cisd.openbis.systemtest.api.v1;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.fail;
 
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.EnumSet;
 import java.util.List;
 
@@ -40,6 +42,7 @@ import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDeta
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.EntityRegistrationDetails.EntityRegistrationDetailsInitializer;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment.ExperimentInitializer;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.PropertyTypeGroup;
@@ -574,6 +577,23 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertEquals(expectedEntities, identifiers.toString());
     }
 
+    private interface IToStringDelegate<T>
+    {
+        String toString(T t);
+    }
+
+    private <T> void assertCollection(String expectedEntities, List<T> entities,
+            IToStringDelegate<T> toStringMethod)
+    {
+        List<String> identifiers = new ArrayList<String>();
+        for (T entity : entities)
+        {
+            identifiers.add(toStringMethod.toString(entity));
+        }
+        Collections.sort(identifiers);
+        assertEquals(expectedEntities, identifiers.toString());
+    }
+
     private void assertDataSets(String expectedDataSets, List<DataSet> dataSets)
     {
         List<String> codes = new ArrayList<String>();
@@ -584,4 +604,68 @@ public class GeneralInformationServiceTest extends SystemTestCase
         Collections.sort(codes);
         assertEquals(expectedDataSets, codes.toString());
     }
+
+    @Test
+    public void testSearchForMaterialsReferencing() throws java.text.ParseException
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE,
+                "SELF_REF"));
+
+        List<Material> materials =
+                generalInformationService.searchForMaterials(sessionToken, searchCriteria);
+
+        assertCollection("[SRM_1, SRM_1A]", materials, new IToStringDelegate<Material>()
+            {
+                public String toString(Material t)
+                {
+                    return t.getMaterialCode();
+                }
+            });
+
+        Material smr1 = materials.get(0);
+        Material smr1a = materials.get(1);
+
+        assertEquals("SRM_1", smr1.getMaterialCode());
+        assertEquals("SRM_1A", smr1a.getMaterialCode());
+
+        assertEquals("Material with attached material", smr1.getProperties().get("DESCRIPTION"));
+        assertEquals("Material wich is attached material", smr1a.getProperties().get("DESCRIPTION"));
+
+        assertEquals("Referenced material should be srm_1a", smr1a.getMaterialCode(), smr1
+                .getMaterialProperties().get("ANY_MATERIAL").getMaterialCode());
+
+        assertEquals("Referenced material should be present in properties as code", String.format(
+                "%s (%s)", smr1a.getMaterialCode(), smr1a.getMaterialTypeIdentifier()
+                        .getMaterialTypeCode()), smr1.getProperties().get("ANY_MATERIAL"));
+
+        Date date2012 = new SimpleDateFormat("yyyy-MM-dd").parse("2012-01-02");
+        Date date2013 = new SimpleDateFormat("yyyy-MM-dd").parse("2013-01-02");
+
+        assertEquals("The date should be after 2012", true, smr1.getRegistrationDetails()
+                .getRegistrationDate().after(date2012));
+        assertEquals("The date should be before 2013", true, smr1.getRegistrationDetails()
+                .getRegistrationDate().before(date2013));
+    }
+
+    @Test
+    public void testSearchForMaterials()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE,
+                "BACTERIUM"));
+
+        List<Material> materials =
+                generalInformationService.searchForMaterials(sessionToken, searchCriteria);
+
+        assertCollection("[BACTERIUM-X, BACTERIUM-Y, BACTERIUM1, BACTERIUM2]", materials,
+                new IToStringDelegate<Material>()
+                    {
+                        public String toString(Material t)
+                        {
+                            return t.getMaterialCode();
+                        }
+                    });
+    }
+
 }