From add32d5a22a3688a22da99a7135c7258252556f9 Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Thu, 13 Dec 2012 15:51:21 +0000
Subject: [PATCH] SP-435 / BIS-219: Make entity retrieval API for validation
 complete - parents and children part

SVN: 27928
---
 .../EntityAdaptorRelationsLoader.java         | 97 +++++++++++++++++++
 .../calculator/EntityTypeRecord.java          | 29 ++++++
 .../calculator/ExternalDataAdaptor.java       | 34 +++----
 .../ExternalDataAdaptorRelationsLoader.java   | 91 +++++++++++++++++
 .../IExternalDataAdaptorRelationsQuery.java   | 54 +++++++++++
 .../ISampleAdaptorRelationsQuery.java         | 57 +++++++++++
 .../calculator/SampleAdaptor.java             | 33 +++----
 .../SampleAdaptorRelationsLoader.java         | 91 +++++++++++++++++
 .../calculator/api/IDataAdaptor.java          | 16 ++-
 .../calculator/api/ISampleAdaptor.java        | 16 ++-
 .../generic/shared/basic/BasicConstant.java   |  5 +-
 .../systemtest/server/CommonServerTest.java   |  5 +-
 .../dataset_adaptor_test__children.py         |  2 +
 .../dataset_adaptor_test__parents.py          |  2 +
 .../sample_adaptor_test__children.py          |  2 +
 .../sample_adaptor_test__parents.py           |  3 +
 16 files changed, 495 insertions(+), 42 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityAdaptorRelationsLoader.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityTypeRecord.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptorRelationsLoader.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/IExternalDataAdaptorRelationsQuery.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ISampleAdaptorRelationsQuery.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptorRelationsLoader.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityAdaptorRelationsLoader.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityAdaptorRelationsLoader.java
new file mode 100644
index 00000000000..c1d893f0c0e
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityAdaptorRelationsLoader.java
@@ -0,0 +1,97 @@
+/*
+ * 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.dataaccess.dynamic_property.calculator;
+
+import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.hibernate.Criteria;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Session;
+import org.hibernate.criterion.Restrictions;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.IDynamicPropertyEvaluator;
+
+/**
+ * @author pkupczyk
+ */
+public class EntityAdaptorRelationsLoader
+{
+
+    private Long entityId;
+
+    private IDynamicPropertyEvaluator evaluator;
+
+    private Session session;
+
+    public EntityAdaptorRelationsLoader(Long entityId, IDynamicPropertyEvaluator evaluator,
+            Session session)
+    {
+        this.entityId = entityId;
+        this.evaluator = evaluator;
+        this.session = session;
+    }
+
+    public <T> Iterable<T> entitiesOfType(Class<?> entityClass, String entityTypeRegexp,
+            IEntityTypesLoader entityTypesLoader, IEntityIdsOfTypesLoader entityIdsOfTypesLoader)
+    {
+        List<EntityTypeRecord> allTypes = entityTypesLoader.loadEntityTypes();
+        LongSet matchingTypeIds = new LongOpenHashSet();
+
+        if (allTypes != null)
+        {
+            for (EntityTypeRecord type : allTypes)
+            {
+                if (type.code.matches(entityTypeRegexp))
+                {
+                    matchingTypeIds.add(type.id);
+                }
+            }
+        }
+
+        if (matchingTypeIds.isEmpty())
+        {
+            return Collections.emptyList();
+        } else
+        {
+            List<Long> parentIds =
+                    entityIdsOfTypesLoader.loadEntityIdsOfTypes(entityId, matchingTypeIds);
+            Criteria criteria = session.createCriteria(entityClass);
+            criteria.setFetchSize(10);
+            criteria.add(Restrictions.in("id", parentIds));
+            ScrollableResults results = criteria.scroll(ScrollMode.FORWARD_ONLY);
+            return new EntityAdaptorIterator<T>(results, evaluator, session);
+        }
+    }
+
+    public static interface IEntityTypesLoader
+    {
+        public List<EntityTypeRecord> loadEntityTypes();
+
+    }
+
+    public static interface IEntityIdsOfTypesLoader
+    {
+        public List<Long> loadEntityIdsOfTypes(Long entityId, LongSet entityTypeIds);
+
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityTypeRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityTypeRecord.java
new file mode 100644
index 00000000000..7c519529ea1
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/EntityTypeRecord.java
@@ -0,0 +1,29 @@
+/*
+ * 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.dataaccess.dynamic_property.calculator;
+
+/**
+ * @author pkupczyk
+ */
+public class EntityTypeRecord
+{
+
+    public Long id;
+
+    public String code;
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptor.java
index f88804affb5..440a90c042a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptor.java
@@ -16,9 +16,6 @@
 
 package ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.lucene.search.Query;
 import org.hibernate.ScrollableResults;
 import org.hibernate.Session;
@@ -29,7 +26,6 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calcu
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.api.IExperimentAdaptor;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.api.ISampleAdaptor;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetRelationshipPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
@@ -87,25 +83,27 @@ public class ExternalDataAdaptor extends AbstractEntityAdaptor implements IDataA
     @Override
     public Iterable<IDataAdaptor> parents()
     {
-        List<IDataAdaptor> list = new ArrayList<IDataAdaptor>();
-        for (DataSetRelationshipPE relationship : externalDataPE.getParentRelationships())
-        {
-            DataPE parent = relationship.getParentDataSet();
-            list.add(EntityAdaptorFactory.create(parent, evaluator, session));
-        }
-        return list;
+        return parentsOfType(ENTITY_TYPE_ANY_CODE_REGEXP);
+    }
+
+    @Override
+    public Iterable<IDataAdaptor> parentsOfType(String typeCodeRegexp)
+    {
+        return new ExternalDataAdaptorRelationsLoader(externalDataPE, evaluator, session)
+                .parentsOfType(typeCodeRegexp);
     }
 
     @Override
     public Iterable<IDataAdaptor> children()
     {
-        List<IDataAdaptor> list = new ArrayList<IDataAdaptor>();
-        for (DataSetRelationshipPE relationship : externalDataPE.getChildRelationships())
-        {
-            DataPE child = relationship.getChildDataSet();
-            list.add(EntityAdaptorFactory.create(child, evaluator, session));
-        }
-        return list;
+        return childrenOfType(ENTITY_TYPE_ANY_CODE_REGEXP);
+    }
+
+    @Override
+    public Iterable<IDataAdaptor> childrenOfType(String typeCodeRegexp)
+    {
+        return new ExternalDataAdaptorRelationsLoader(externalDataPE, evaluator, session)
+                .childrenOfType(typeCodeRegexp);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptorRelationsLoader.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptorRelationsLoader.java
new file mode 100644
index 00000000000..c016357eec8
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ExternalDataAdaptorRelationsLoader.java
@@ -0,0 +1,91 @@
+/*
+ * 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.dataaccess.dynamic_property.calculator;
+
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+import java.util.List;
+
+import net.lemnik.eodsql.QueryTool;
+
+import org.hibernate.Session;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.IDynamicPropertyEvaluator;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.EntityAdaptorRelationsLoader.IEntityIdsOfTypesLoader;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.EntityAdaptorRelationsLoader.IEntityTypesLoader;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.api.IDataAdaptor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
+
+/**
+ * @author pkupczyk
+ */
+public class ExternalDataAdaptorRelationsLoader
+{
+
+    private EntityAdaptorRelationsLoader relationsLoader;
+
+    private IExternalDataAdaptorRelationsQuery relationsQuery;
+
+    public ExternalDataAdaptorRelationsLoader(DataPE data, IDynamicPropertyEvaluator evaluator,
+            Session session)
+    {
+        this.relationsLoader = new EntityAdaptorRelationsLoader(data.getId(), evaluator, session);
+        this.relationsQuery = QueryTool.getManagedQuery(IExternalDataAdaptorRelationsQuery.class);
+    }
+
+    public Iterable<IDataAdaptor> parentsOfType(String typeRegexp)
+    {
+        return relationsLoader.entitiesOfType(DataPE.class, typeRegexp, new IEntityTypesLoader()
+            {
+                @Override
+                public List<EntityTypeRecord> loadEntityTypes()
+                {
+                    return relationsQuery.getDataSetTypes();
+                }
+            }, new IEntityIdsOfTypesLoader()
+            {
+
+                @Override
+                public List<Long> loadEntityIdsOfTypes(Long entityId, LongSet entityTypeIds)
+                {
+                    return relationsQuery.getParentIdsOfTypes(entityId, entityTypeIds);
+                }
+            });
+    }
+
+    public Iterable<IDataAdaptor> childrenOfType(String typeRegexp)
+    {
+        return relationsLoader.entitiesOfType(DataPE.class, typeRegexp, new IEntityTypesLoader()
+            {
+
+                @Override
+                public List<EntityTypeRecord> loadEntityTypes()
+                {
+                    return relationsQuery.getDataSetTypes();
+                }
+            }, new IEntityIdsOfTypesLoader()
+            {
+
+                @Override
+                public List<Long> loadEntityIdsOfTypes(Long entityId, LongSet entityTypeIds)
+                {
+                    return relationsQuery.getChildIdsOfTypes(entityId, entityTypeIds);
+                }
+            });
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/IExternalDataAdaptorRelationsQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/IExternalDataAdaptorRelationsQuery.java
new file mode 100644
index 00000000000..cfb33ec28e9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/IExternalDataAdaptorRelationsQuery.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.generic.server.dataaccess.dynamic_property.calculator;
+
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+import java.util.List;
+
+import net.lemnik.eodsql.BaseQuery;
+import net.lemnik.eodsql.Select;
+import net.lemnik.eodsql.TypeMapper;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.LongSetMapper;
+
+/**
+ * @author pkupczyk
+ */
+public interface IExternalDataAdaptorRelationsQuery extends BaseQuery
+{
+
+    public int FETCH_SIZE = 1000;
+
+    @Select(sql = "SELECT id, code FROM data_set_types", fetchSize = FETCH_SIZE)
+    public List<EntityTypeRecord> getDataSetTypes();
+
+    @Select(sql = "SELECT dsr.data_id_parent FROM data_set_relationships dsr, "
+            + " data d, data_set_types dst WHERE "
+            + " dsr.data_id_parent = d.id AND d.dsty_id = dst.id AND "
+            + " dsr.data_id_child = ?{1} AND dst.id = any(?{2})", parameterBindings =
+        { TypeMapper.class, LongSetMapper.class }, fetchSize = FETCH_SIZE)
+    public List<Long> getParentIdsOfTypes(Long childId, LongSet parentTypeIds);
+
+    @Select(sql = "SELECT dsr.data_id_child FROM data_set_relationships dsr, "
+            + " data d, data_set_types dst WHERE "
+            + " dsr.data_id_child = d.id AND d.dsty_id = dst.id AND "
+            + " dsr.data_id_parent = ?{1} AND dst.id = any(?{2})", parameterBindings =
+        { TypeMapper.class, LongSetMapper.class }, fetchSize = FETCH_SIZE)
+    public List<Long> getChildIdsOfTypes(Long parentId, LongSet childTypeIds);
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ISampleAdaptorRelationsQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ISampleAdaptorRelationsQuery.java
new file mode 100644
index 00000000000..0025036d9cf
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/ISampleAdaptorRelationsQuery.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.generic.server.dataaccess.dynamic_property.calculator;
+
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+import java.util.List;
+
+import net.lemnik.eodsql.BaseQuery;
+import net.lemnik.eodsql.Select;
+import net.lemnik.eodsql.TypeMapper;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.LongSetMapper;
+import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
+
+/**
+ * @author pkupczyk
+ */
+public interface ISampleAdaptorRelationsQuery extends BaseQuery
+{
+
+    public int FETCH_SIZE = 1000;
+
+    @Select(sql = "SELECT id, code FROM sample_types", fetchSize = FETCH_SIZE)
+    public List<EntityTypeRecord> getSampleTypes();
+
+    @Select(sql = "SELECT sr.sample_id_parent FROM sample_relationships sr, "
+            + " relationship_types rt, samples s, sample_types st WHERE "
+            + " sr.relationship_id = rt.id AND sr.sample_id_parent = s.id AND "
+            + " s.saty_id = st.id AND sr.sample_id_child = ?{1} AND " + " rt.code = '"
+            + BasicConstant.PARENT_CHILD_DB_RELATIONSHIP + "' AND st.id = any(?{2})", parameterBindings =
+        { TypeMapper.class, LongSetMapper.class }, fetchSize = FETCH_SIZE)
+    public List<Long> getParentIdsOfTypes(Long childId, LongSet parentTypeIds);
+
+    @Select(sql = "SELECT sr.sample_id_child FROM sample_relationships sr, "
+            + " relationship_types rt, samples s, sample_types st WHERE "
+            + " sr.relationship_id = rt.id AND sr.sample_id_child = s.id AND "
+            + " s.saty_id = st.id AND sr.sample_id_parent = ?{1} AND " + " rt.code = '"
+            + BasicConstant.PARENT_CHILD_DB_RELATIONSHIP + "' AND st.id = any(?{2})", parameterBindings =
+        { TypeMapper.class, LongSetMapper.class }, fetchSize = FETCH_SIZE)
+    public List<Long> getChildIdsOfTypes(Long parentId, LongSet childTypeIds);
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptor.java
index 5eecd5e0dfa..739266a64f6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptor.java
@@ -16,9 +16,6 @@
 
 package ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.lucene.search.Query;
 import org.hibernate.ScrollableResults;
 import org.hibernate.Session;
@@ -30,7 +27,6 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calcu
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.api.ISampleAdaptor;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
-import ch.systemsx.cisd.openbis.generic.shared.dto.SampleRelationshipPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.hibernate.SearchFieldConstants;
 
 /**
@@ -72,24 +68,27 @@ public class SampleAdaptor extends AbstractEntityAdaptor implements ISampleAdapt
     @Override
     public Iterable<ISampleAdaptor> parents()
     {
-        List<ISampleAdaptor> list = new ArrayList<ISampleAdaptor>();
-        for (SamplePE parent : samplePE.getParents())
-        {
-            list.add(EntityAdaptorFactory.create(parent, evaluator, session));
-        }
-        return list;
+        return parentsOfType(ENTITY_TYPE_ANY_CODE_REGEXP);
+    }
+
+    @Override
+    public Iterable<ISampleAdaptor> parentsOfType(String typeCodeRegexp)
+    {
+        return new SampleAdaptorRelationsLoader(samplePE, evaluator, session)
+                .parentsOfType(typeCodeRegexp);
     }
 
     @Override
     public Iterable<ISampleAdaptor> children()
     {
-        List<ISampleAdaptor> list = new ArrayList<ISampleAdaptor>();
-        for (SampleRelationshipPE relationship : samplePE.getChildRelationships())
-        {
-            SamplePE child = relationship.getChildSample();
-            list.add(EntityAdaptorFactory.create(child, evaluator, session));
-        }
-        return list;
+        return childrenOfType(ENTITY_TYPE_ANY_CODE_REGEXP);
+    }
+
+    @Override
+    public Iterable<ISampleAdaptor> childrenOfType(String typeCodeRegexp)
+    {
+        return new SampleAdaptorRelationsLoader(samplePE, evaluator, session)
+                .childrenOfType(typeCodeRegexp);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptorRelationsLoader.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptorRelationsLoader.java
new file mode 100644
index 00000000000..6723dbc97d9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/SampleAdaptorRelationsLoader.java
@@ -0,0 +1,91 @@
+/*
+ * 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.dataaccess.dynamic_property.calculator;
+
+import it.unimi.dsi.fastutil.longs.LongSet;
+
+import java.util.List;
+
+import net.lemnik.eodsql.QueryTool;
+
+import org.hibernate.Session;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.IDynamicPropertyEvaluator;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.EntityAdaptorRelationsLoader.IEntityIdsOfTypesLoader;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.EntityAdaptorRelationsLoader.IEntityTypesLoader;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.calculator.api.ISampleAdaptor;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE;
+
+/**
+ * @author pkupczyk
+ */
+public class SampleAdaptorRelationsLoader
+{
+
+    private EntityAdaptorRelationsLoader relationsLoader;
+
+    private ISampleAdaptorRelationsQuery relationsQuery;
+
+    public SampleAdaptorRelationsLoader(SamplePE sample, IDynamicPropertyEvaluator evaluator,
+            Session session)
+    {
+        this.relationsLoader = new EntityAdaptorRelationsLoader(sample.getId(), evaluator, session);
+        this.relationsQuery = QueryTool.getManagedQuery(ISampleAdaptorRelationsQuery.class);
+    }
+
+    public Iterable<ISampleAdaptor> parentsOfType(String typeRegexp)
+    {
+        return relationsLoader.entitiesOfType(SamplePE.class, typeRegexp, new IEntityTypesLoader()
+            {
+                @Override
+                public List<EntityTypeRecord> loadEntityTypes()
+                {
+                    return relationsQuery.getSampleTypes();
+                }
+            }, new IEntityIdsOfTypesLoader()
+            {
+
+                @Override
+                public List<Long> loadEntityIdsOfTypes(Long entityId, LongSet entityTypeIds)
+                {
+                    return relationsQuery.getParentIdsOfTypes(entityId, entityTypeIds);
+                }
+            });
+    }
+
+    public Iterable<ISampleAdaptor> childrenOfType(String typeRegexp)
+    {
+        return relationsLoader.entitiesOfType(SamplePE.class, typeRegexp, new IEntityTypesLoader()
+            {
+
+                @Override
+                public List<EntityTypeRecord> loadEntityTypes()
+                {
+                    return relationsQuery.getSampleTypes();
+                }
+            }, new IEntityIdsOfTypesLoader()
+            {
+
+                @Override
+                public List<Long> loadEntityIdsOfTypes(Long entityId, LongSet entityTypeIds)
+                {
+                    return relationsQuery.getChildIdsOfTypes(entityId, entityTypeIds);
+                }
+            });
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/IDataAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/IDataAdaptor.java
index a242641a0db..6b84c1a342a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/IDataAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/IDataAdaptor.java
@@ -32,15 +32,27 @@ public interface IDataAdaptor
     public ISampleAdaptor sample();
 
     /**
-     * Returns all parent data sets.
+     * Returns parent data sets of this data set.
      */
     public Iterable<IDataAdaptor> parents();
 
     /**
-     * Returns all child data sets.
+     * Returns parent data sets of this data set. Types of the returned parent data sets must match
+     * the specified regular expression.
+     */
+    public Iterable<IDataAdaptor> parentsOfType(String typeCodeRegexp);
+
+    /**
+     * Returns child data sets of this data set.
      */
     public Iterable<IDataAdaptor> children();
 
+    /**
+     * Returns child data sets of this data set. Types of the returned child data sets must match
+     * the specified regular expression.
+     */
+    public Iterable<IDataAdaptor> childrenOfType(String typeCodeRegexp);
+
     /**
      * Returns the container data set, or null if not exists.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/ISampleAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/ISampleAdaptor.java
index c1439cc7d21..37d3d2b2662 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/ISampleAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/dynamic_property/calculator/api/ISampleAdaptor.java
@@ -27,15 +27,27 @@ public interface ISampleAdaptor extends IEntityAdaptor
     public IExperimentAdaptor experiment();
 
     /**
-     * Returns all parent samples.
+     * Returns parent samples of this sample.
      */
     public Iterable<ISampleAdaptor> parents();
 
     /**
-     * Returns all child samples.
+     * Returns parent samples of this sample. Types of the returned parent samples must match the
+     * specified regular expression.
+     */
+    public Iterable<ISampleAdaptor> parentsOfType(String typeCodeRegexp);
+
+    /**
+     * Returns child samples of this sample.
      */
     public Iterable<ISampleAdaptor> children();
 
+    /**
+     * Returns child samples of this sample. Types of the returned child samples must match the
+     * specified regular expression.
+     */
+    public Iterable<ISampleAdaptor> childrenOfType(String typeCodeRegexp);
+
     /**
      * Returns the container sample, or null if not exists.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
index 1887e6157c1..9cc9b86de6f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java
@@ -121,7 +121,10 @@ public class BasicConstant
 
     public static final String LOCATOR_ACTION_PARAMETER = "action";
 
-    public static final String PARENT_CHILD_INTERNAL_RELATIONSHIP = "$PARENT_CHILD";
+    public static final String PARENT_CHILD_DB_RELATIONSHIP = "PARENT_CHILD";
+
+    public static final String PARENT_CHILD_INTERNAL_RELATIONSHIP = INTERNAL_NAMESPACE_PREFIX
+            + PARENT_CHILD_DB_RELATIONSHIP;
 
     public static final String SERVER_URL_PARAMETER = "server-url";
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTest.java
index 7734ff3160a..62d080b2f1d 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTest.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.systemtest.server;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 
 import junit.framework.Assert;
@@ -185,8 +186,8 @@ public class CommonServerTest extends SystemTestCase
     {
         try
         {
-            return IOUtils.toString(getClass().getResourceAsStream(
-                    "CommonServerTestResources" + File.separator + fileName));
+            return IOUtils.toString(new FileInputStream(new File("sourceTest/java/"
+                    + getClass().getName().replace(".", "/") + "Resources" + "/" + fileName)));
         } catch (IOException ex)
         {
             throw new RuntimeException(ex);
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__children.py b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__children.py
index c34f34f777a..410fb969006 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__children.py
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__children.py
@@ -1,5 +1,7 @@
 def validate(dataset, isNew):
     try:
         assertEntities(dataset.children(), ["20081105092259900-0", "20081105092259900-1"], 'children')
+        assertEntities(dataset.childrenOfType('HCS_IMAGE'), ["20081105092259900-0", "20081105092259900-1"], 'children of type HCS_IMAGE')
+        assertEntities(dataset.childrenOfType('NOT_EXISTING_TYPE'), [], 'children of type NOT_EXISTING_TYPE')
     except Exception, ex:
         return ex.args[0]
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__parents.py b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__parents.py
index 1b9f22276c8..77b46634d65 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__parents.py
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/dataset_adaptor_test__parents.py
@@ -1,5 +1,7 @@
 def validate(dataset, isNew):
     try:
         assertEntities(dataset.parents(), ["20081105092159111-1", "20081105092159222-2", "20081105092159333-3"], 'parents')
+        assertEntities(dataset.parentsOfType('HCS_IMAGE'), ["20081105092159111-1", "20081105092159222-2", "20081105092159333-3"], 'parents of type HCS_IMAGE')
+        assertEntities(dataset.parentsOfType('NOT_EXISTING_TYPE'), [], 'parents of type NOT_EXISTING_TYPE')
     except Exception, ex:
         return ex.args[0]
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__children.py b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__children.py
index cd5c79e558f..3e1648449d0 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__children.py
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__children.py
@@ -1,5 +1,7 @@
 def validate(sample, isNew):
     try:
         assertEntities(sample.children(), ['CP1-A1','CP1-A2'], 'children')
+        assertEntities(sample.childrenOfType('CELL_PLATE'), ['CP1-A1','CP1-A2'], 'children of type CELL_PLATE')
+        assertEntities(sample.childrenOfType('NOT_EXISTING_TYPE'), [], 'children of type NOT_EXISTING_TYPE')
     except Exception, ex:
         return ex.args[0]
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__parents.py b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__parents.py
index bf5b4c81a4f..803f6506f5f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__parents.py
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/server/CommonServerTestResources/sample_adaptor_test__parents.py
@@ -1,5 +1,8 @@
 def validate(sample, isNew):
     try:
         assertEntities(sample.parents(), ['A02','3V-125'], 'parents')
+        assertEntities(sample.parentsOfType('DILUTION_PLATE'), ['3V-125'], 'parents of type DILUTION_PLATE')
+        assertEntities(sample.parentsOfType('WELL'), ['A02'], 'parents of type WELL')
+        assertEntities(sample.parentsOfType('NOT_EXISTING_TYPE'), [], 'parents of type NOT_EXISTING_TYPE')
     except Exception, ex:
         return ex.args[0]
-- 
GitLab