From c9b156eb28dbc479d2b1ef38846e038d897d5f95 Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Tue, 10 Nov 2015 12:56:52 +0000
Subject: [PATCH] SSDM-2636 : V3 AS API - sort search results by property
 values: - change sort options - make property() method available only for
 entities that can have properties - extend IPropertiesHolder with
 getProperty(), getMaterialProperty() methods

SVN: 35023
---
 .../dataset/DataSetSortOptions.js             |  6 +-
 .../experiment/ExperimentSortOptions.js       |  6 +-
 .../material/MaterialSortOptions.js           |  6 +-
 .../fetchoptions/sample/SampleSortOptions.js  |  6 +-
 .../fetchoptions/sort/EntitySortOptions.js    | 11 +---
 .../sort/EntityWithPropertiesSortOptions.js   | 23 +++++++
 .../api/v3/dto/entity/dataset/DataSet.java    | 12 ++++
 .../v3/dto/entity/experiment/Experiment.java  | 12 ++++
 .../entity/interfaces/IPropertiesHolder.java  |  6 ++
 .../api/v3/dto/entity/material/Material.java  | 12 ++++
 .../api/v3/dto/entity/sample/Sample.java      | 12 ++++
 .../dataset/DataSetSortOptions.java           |  4 +-
 .../experiment/ExperimentSortOptions.java     |  4 +-
 .../material/MaterialSortOptions.java         |  4 +-
 .../sample/SampleSortOptions.java             |  4 +-
 .../fetchoptions/sort/EntitySortOptions.java  | 15 -----
 .../sort/EntityWithPropertiesSortOptions.java | 61 +++++++++++++++++++
 .../sort/comparator/PropertyComparator.java   | 14 +----
 .../v3/dto/generators/AbstractGenerator.java  | 13 ++++
 .../api/v3/dto/generators/DtoGenerator.java   | 19 ++++++
 20 files changed, 193 insertions(+), 57 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.js
 create mode 100644 openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.js
index 7266ffbcc4d..9109ae6c044 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.js
@@ -1,8 +1,8 @@
-define([ "require", "stjs", "dto/fetchoptions/sort/EntitySortOptions" ], function(require, stjs, EntitySortOptions) {
+define([ "require", "stjs", "dto/fetchoptions/sort/EntityWithPropertiesSortOptions" ], function(require, stjs, EntityWithPropertiesSortOptions) {
 	var DataSetSortOptions = function() {
-		EntitySortOptions.call(this);
+		EntityWithPropertiesSortOptions.call(this);
 	};
-	stjs.extend(DataSetSortOptions, EntitySortOptions, [ EntitySortOptions ], function(constructor, prototype) {
+	stjs.extend(DataSetSortOptions, EntityWithPropertiesSortOptions, [ EntityWithPropertiesSortOptions ], function(constructor, prototype) {
 		prototype['@type'] = 'dto.fetchoptions.dataset.DataSetSortOptions';
 		constructor.serialVersionUID = 1;
 	}, {});
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.js
index 97200dedd2a..36006336e54 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.js
@@ -1,8 +1,8 @@
-define([ "require", "stjs", "dto/fetchoptions/sort/EntitySortOptions" ], function(require, stjs, EntitySortOptions) {
+define([ "require", "stjs", "dto/fetchoptions/sort/EntityWithPropertiesSortOptions" ], function(require, stjs, EntityWithPropertiesSortOptions) {
 	var ExperimentSortOptions = function() {
-		EntitySortOptions.call(this);
+		EntityWithPropertiesSortOptions.call(this);
 	};
-	stjs.extend(ExperimentSortOptions, EntitySortOptions, [ EntitySortOptions ], function(constructor, prototype) {
+	stjs.extend(ExperimentSortOptions, EntityWithPropertiesSortOptions, [ EntityWithPropertiesSortOptions ], function(constructor, prototype) {
 		prototype['@type'] = 'dto.fetchoptions.experiment.ExperimentSortOptions';
 		constructor.serialVersionUID = 1;
 	}, {});
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/material/MaterialSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/material/MaterialSortOptions.js
index 055ed196e10..518d5701d83 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/material/MaterialSortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/material/MaterialSortOptions.js
@@ -1,8 +1,8 @@
-define([ "require", "stjs", "dto/fetchoptions/sort/EntitySortOptions" ], function(require, stjs, EntitySortOptions) {
+define([ "require", "stjs", "dto/fetchoptions/sort/EntityWithPropertiesSortOptions" ], function(require, stjs, EntityWithPropertiesSortOptions) {
 	var MaterialSortOptions = function() {
-		EntitySortOptions.call(this);
+		EntityWithPropertiesSortOptions.call(this);
 	};
-	stjs.extend(MaterialSortOptions, EntitySortOptions, [ EntitySortOptions ], function(constructor, prototype) {
+	stjs.extend(MaterialSortOptions, EntityWithPropertiesSortOptions, [ EntityWithPropertiesSortOptions ], function(constructor, prototype) {
 		prototype['@type'] = 'dto.fetchoptions.material.MaterialSortOptions';
 		constructor.serialVersionUID = 1;
 	}, {});
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sample/SampleSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sample/SampleSortOptions.js
index a17f67020a3..0fe19869860 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sample/SampleSortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sample/SampleSortOptions.js
@@ -1,8 +1,8 @@
-define([ "require", "stjs", "dto/fetchoptions/sort/EntitySortOptions" ], function(require, stjs, EntitySortOptions) {
+define([ "require", "stjs", "dto/fetchoptions/sort/EntityWithPropertiesSortOptions" ], function(require, stjs, EntityWithPropertiesSortOptions) {
 	var SampleSortOptions = function() {
-		EntitySortOptions.call(this);
+		EntityWithPropertiesSortOptions.call(this);
 	};
-	stjs.extend(SampleSortOptions, EntitySortOptions, [ EntitySortOptions ], function(constructor, prototype) {
+	stjs.extend(SampleSortOptions, EntityWithPropertiesSortOptions, [ EntityWithPropertiesSortOptions ], function(constructor, prototype) {
 		prototype['@type'] = 'dto.fetchoptions.sample.SampleSortOptions';
 		constructor.serialVersionUID = 1;
 	}, {});
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntitySortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntitySortOptions.js
index 015ebf585ac..665d45d821c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntitySortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntitySortOptions.js
@@ -6,8 +6,7 @@ define([ "require", "stjs", "dto/fetchoptions/sort/SortOptions" ], function(requ
 	var fields = {
 		CODE : "CODE",
 		REGISTRATION_DATE : "REGISTRATION_DATE",
-		MODIFICATION_DATE : "MODIFICATION_DATE",
-		PROPERTY : "PROPERTY"
+		MODIFICATION_DATE : "MODIFICATION_DATE"
 	};
 
 	stjs.extend(EntitySortOptions, SortOptions, [ SortOptions ], function(constructor, prototype) {
@@ -19,14 +18,6 @@ define([ "require", "stjs", "dto/fetchoptions/sort/SortOptions" ], function(requ
 		prototype.getCode = function() {
 			return this.getSorting(fields.CODE);
 		};
-
-		prototype.property = function(propertyName) {
-			return this.getOrCreateSorting(fields.PROPERTY + propertyName);
-		};
-		prototype.getProperty = function(propertyName) {
-			return this.getSorting(fields.PROPERTY + propertyName);
-		};
-
 		prototype.registrationDate = function() {
 			return this.getOrCreateSorting(fields.REGISTRATION_DATE);
 		};
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.js
new file mode 100644
index 00000000000..96836842573
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.js
@@ -0,0 +1,23 @@
+define([ "require", "stjs", "dto/fetchoptions/sort/EntitySortOptions" ], function(require, stjs, EntitySortOptions) {
+	var EntityWithPropertiesSortOptions = function() {
+		EntitySortOptions.call(this);
+	};
+
+	var fields = {
+		PROPERTY : "PROPERTY"
+	};
+
+	stjs.extend(EntityWithPropertiesSortOptions, EntitySortOptions, [ EntitySortOptions ], function(constructor, prototype) {
+		prototype['@type'] = 'dto.fetchoptions.sort.EntityWithPropertiesSortOptions';
+		constructor.serialVersionUID = 1;
+
+		prototype.property = function(propertyName) {
+			return this.getOrCreateSorting(fields.PROPERTY + propertyName);
+		};
+		prototype.getProperty = function(propertyName) {
+			return this.getSorting(fields.PROPERTY + propertyName);
+		};
+
+	}, {});
+	return EntityWithPropertiesSortOptions;
+})
\ No newline at end of file
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSet.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSet.java
index b05a7e395ab..d500db1204a 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSet.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/dataset/DataSet.java
@@ -561,6 +561,18 @@ public class DataSet implements Serializable, ICodeHolder, IModificationDateHold
         this.accessDate = accessDate;
     }
 
+    @Override
+    public String getProperty(String propertyName)
+    {
+        return getProperties() != null ? getProperties().get(propertyName) : null;
+    }
+
+    @Override
+    public Material getMaterialProperty(String propertyName)
+    {
+        return getMaterialProperties() != null ? getMaterialProperties().get(propertyName) : null;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/experiment/Experiment.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/experiment/Experiment.java
index 97df4e23397..b3d9a6efa9c 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/experiment/Experiment.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/experiment/Experiment.java
@@ -413,6 +413,18 @@ public class Experiment implements Serializable, IAttachmentsHolder, ICodeHolder
         this.attachments = attachments;
     }
 
+    @Override
+    public String getProperty(String propertyName)
+    {
+        return getProperties() != null ? getProperties().get(propertyName) : null;
+    }
+
+    @Override
+    public Material getMaterialProperty(String propertyName)
+    {
+        return getMaterialProperties() != null ? getMaterialProperties().get(propertyName) : null;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/interfaces/IPropertiesHolder.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/interfaces/IPropertiesHolder.java
index 9ed13b342d5..94b9189dc90 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/interfaces/IPropertiesHolder.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/interfaces/IPropertiesHolder.java
@@ -25,7 +25,13 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.material.Material;
  */
 public interface IPropertiesHolder
 {
+
     Map<String, String> getProperties();
 
+    String getProperty(String propertyName);
+
     Map<String, Material> getMaterialProperties();
+
+    Material getMaterialProperty(String propertyName);
+
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/material/Material.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/material/Material.java
index e9a44669683..51e0151a557 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/material/Material.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/material/Material.java
@@ -273,6 +273,18 @@ public class Material implements Serializable, ICodeHolder, IModificationDateHol
         this.tags = tags;
     }
 
+    @Override
+    public String getProperty(String propertyName)
+    {
+        return getProperties() != null ? getProperties().get(propertyName) : null;
+    }
+
+    @Override
+    public Material getMaterialProperty(String propertyName)
+    {
+        return getMaterialProperties() != null ? getMaterialProperties().get(propertyName) : null;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/sample/Sample.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/sample/Sample.java
index a513721512e..363d70cfb86 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/sample/Sample.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/entity/sample/Sample.java
@@ -535,6 +535,18 @@ public class Sample implements Serializable, IAttachmentsHolder, ICodeHolder, IM
         this.attachments = attachments;
     }
 
+    @Override
+    public String getProperty(String propertyName)
+    {
+        return getProperties() != null ? getProperties().get(propertyName) : null;
+    }
+
+    @Override
+    public Material getMaterialProperty(String propertyName)
+    {
+        return getMaterialProperties() != null ? getMaterialProperties().get(propertyName) : null;
+    }
+
     @Override
     public String toString()
     {
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.java
index 8c8166f08ee..711138ed9d4 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/dataset/DataSetSortOptions.java
@@ -17,14 +17,14 @@
 package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.dataset;
 
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.dataset.DataSet;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntitySortOptions;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntityWithPropertiesSortOptions;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
  * @author pkupczyk
  */
 @JsonObject("dto.fetchoptions.dataset.DataSetSortOptions")
-public class DataSetSortOptions extends EntitySortOptions<DataSet>
+public class DataSetSortOptions extends EntityWithPropertiesSortOptions<DataSet>
 {
 
     private static final long serialVersionUID = 1L;
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.java
index ee929c47b84..78daee18b7e 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/experiment/ExperimentSortOptions.java
@@ -17,14 +17,14 @@
 package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.experiment;
 
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.experiment.Experiment;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntitySortOptions;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntityWithPropertiesSortOptions;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
  * @author pkupczyk
  */
 @JsonObject("dto.fetchoptions.experiment.ExperimentSortOptions")
-public class ExperimentSortOptions extends EntitySortOptions<Experiment>
+public class ExperimentSortOptions extends EntityWithPropertiesSortOptions<Experiment>
 {
 
     private static final long serialVersionUID = 1L;
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/material/MaterialSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/material/MaterialSortOptions.java
index 68866316574..f97a0472f89 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/material/MaterialSortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/material/MaterialSortOptions.java
@@ -17,14 +17,14 @@
 package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.material;
 
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.material.Material;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntitySortOptions;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntityWithPropertiesSortOptions;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
  * @author pkupczyk
  */
 @JsonObject("dto.fetchoptions.material.MaterialSortOptions")
-public class MaterialSortOptions extends EntitySortOptions<Material>
+public class MaterialSortOptions extends EntityWithPropertiesSortOptions<Material>
 {
 
     private static final long serialVersionUID = 1L;
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sample/SampleSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sample/SampleSortOptions.java
index 9ddaa3f983c..242f91348f9 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sample/SampleSortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sample/SampleSortOptions.java
@@ -17,14 +17,14 @@
 package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sample;
 
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.sample.Sample;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntitySortOptions;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.EntityWithPropertiesSortOptions;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
  * @author pkupczyk
  */
 @JsonObject("dto.fetchoptions.sample.SampleSortOptions")
-public class SampleSortOptions extends EntitySortOptions<Sample>
+public class SampleSortOptions extends EntityWithPropertiesSortOptions<Sample>
 {
 
     private static final long serialVersionUID = 1L;
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntitySortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntitySortOptions.java
index 2e1c5ee2478..04296ab2505 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntitySortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntitySortOptions.java
@@ -18,7 +18,6 @@ package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort;
 
 import static ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.CodeComparator.CODE;
 import static ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.ModificationDateComparator.MODIFICATION_DATE;
-import static ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.PropertyComparator.PROPERTY;
 import static ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.RegistrationDateComparator.REGISTRATION_DATE;
 
 import java.util.Comparator;
@@ -28,7 +27,6 @@ import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IModifica
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IRegistrationDateHolder;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.CodeComparator;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.ModificationDateComparator;
-import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.PropertyComparator;
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.RegistrationDateComparator;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
@@ -51,16 +49,6 @@ public class EntitySortOptions<OBJECT extends ICodeHolder & IRegistrationDateHol
         return getSorting(CODE);
     }
 
-    public SortOrder property(String propertyName)
-    {
-        return getOrCreateSorting(PROPERTY + propertyName);
-    }
-
-    public SortOrder getProperty(String propertyName)
-    {
-        return getSorting(PROPERTY + propertyName);
-    }
-
     public SortOrder registrationDate()
     {
         return getOrCreateSorting(REGISTRATION_DATE);
@@ -93,9 +81,6 @@ public class EntitySortOptions<OBJECT extends ICodeHolder & IRegistrationDateHol
         } else if (MODIFICATION_DATE.equals(field))
         {
             return new ModificationDateComparator<OBJECT>();
-        } else if (field.startsWith(PROPERTY))
-        {
-            return new PropertyComparator<OBJECT>(field.substring(PROPERTY.length()));
         } else
         {
             return null;
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.java
new file mode 100644
index 00000000000..f819b2ab60d
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/EntityWithPropertiesSortOptions.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 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.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort;
+
+import static ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.PropertyComparator.PROPERTY;
+
+import java.util.Comparator;
+
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.ICodeHolder;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IModificationDateHolder;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IPropertiesHolder;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IRegistrationDateHolder;
+import ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator.PropertyComparator;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject("dto.fetchoptions.sort.EntityWithPropertiesSortOptions")
+public class EntityWithPropertiesSortOptions<OBJECT extends ICodeHolder & IRegistrationDateHolder & IModificationDateHolder & IPropertiesHolder>
+        extends EntitySortOptions<OBJECT>
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public SortOrder property(String propertyName)
+    {
+        return getOrCreateSorting(PROPERTY + propertyName);
+    }
+
+    public SortOrder getProperty(String propertyName)
+    {
+        return getSorting(PROPERTY + propertyName);
+    }
+
+    @Override
+    public Comparator<OBJECT> getComparator(String field)
+    {
+        if (field.startsWith(PROPERTY))
+        {
+            return new PropertyComparator<OBJECT>(field.substring(PROPERTY.length()));
+        } else
+        {
+            return super.getComparator(field);
+        }
+    }
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/comparator/PropertyComparator.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/comparator/PropertyComparator.java
index b3ae8647d02..84f12509c30 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/comparator/PropertyComparator.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/fetchoptions/sort/comparator/PropertyComparator.java
@@ -16,14 +16,12 @@
 
 package ch.ethz.sis.openbis.generic.shared.api.v3.dto.fetchoptions.sort.comparator;
 
-import java.util.Map;
-
 import ch.ethz.sis.openbis.generic.shared.api.v3.dto.entity.interfaces.IPropertiesHolder;
 
 /**
  * @author pkupczyk
  */
-public class PropertyComparator<OBJECT> extends AbstractStringComparator<OBJECT>
+public class PropertyComparator<OBJECT extends IPropertiesHolder> extends AbstractStringComparator<OBJECT>
 {
 
     public static final String PROPERTY = "PROPERTY";
@@ -38,14 +36,6 @@ public class PropertyComparator<OBJECT> extends AbstractStringComparator<OBJECT>
     @Override
     protected String getValue(OBJECT o)
     {
-        if (o instanceof IPropertiesHolder)
-        {
-            Map<String, String> properties = ((IPropertiesHolder) o).getProperties();
-            return properties != null ? properties.get(propertyName) : null;
-        } else
-        {
-            throw new IllegalArgumentException("Object " + o + " does not implement " + IPropertiesHolder.class
-                    + " interface therefore cannot be sorted by a property value.");
-        }
+        return o.getProperty(propertyName);
     }
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/AbstractGenerator.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/AbstractGenerator.java
index 1a85fdeeaec..c703c0e7283 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/AbstractGenerator.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/AbstractGenerator.java
@@ -100,6 +100,18 @@ public class AbstractGenerator
                 MaterialFetchOptions.class).withInterface(IPropertiesHolder.class);
         gen.addClassForImport(Map.class);
         gen.addClassForImport(Material.class);
+
+        gen.addAdditionalMethod("@Override\n"
+                + "    public String getProperty(String propertyName)\n"
+                + "    {\n"
+                + "        return getProperties() != null ? getProperties().get(propertyName) : null;\n"
+                + "    }");
+
+        gen.addAdditionalMethod("@Override\n"
+                + "    public Material getMaterialProperty(String propertyName)\n"
+                + "    {\n"
+                + "        return getMaterialProperties() != null ? getMaterialProperties().get(propertyName) : null;\n"
+                + "    }");
     }
 
     public static void addAttachments(DtoGenerator gen)
@@ -114,4 +126,5 @@ public class AbstractGenerator
     {
         gen.addSimpleField(String.class, "description");
     }
+
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/DtoGenerator.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/DtoGenerator.java
index f4f3045f229..58828c1e4ec 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/DtoGenerator.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/shared/api/v3/dto/generators/DtoGenerator.java
@@ -33,6 +33,8 @@ public class DtoGenerator
 
     private Set<String> additionalImports;
 
+    private List<String> additionalMethods;
+
     private PrintStream outputStream = System.out;
 
     private Class<?> fetchOptionsClass;
@@ -46,6 +48,7 @@ public class DtoGenerator
         this.subPackage = subPackage;
         this.className = className;
         this.additionalImports = new TreeSet<String>();
+        this.additionalMethods = new LinkedList<String>();
         this.fields = new LinkedList<DtoGenerator.DTOField>();
         this.implementedInterfaces = new TreeSet<String>();
 
@@ -206,6 +209,11 @@ public class DtoGenerator
         return field;
     }
 
+    public void addAdditionalMethod(String method)
+    {
+        additionalMethods.add(method);
+    }
+
     public void addClassForImport(Class<?> c)
     {
         additionalImports.add(c.getName());
@@ -296,6 +304,7 @@ public class DtoGenerator
         printFields();
 
         printAccessors();
+        printAdditionalMethods();
 
         printToString();
 
@@ -800,4 +809,14 @@ public class DtoGenerator
             print("");
         }
     }
+
+    private void printAdditionalMethods()
+    {
+        for (String additionalMethod : additionalMethods)
+        {
+            print(additionalMethod);
+            print("");
+        }
+    }
+
 }
-- 
GitLab