diff --git a/integration-tests/testData/test_scu_microscopy/grte5q85rsp3b147p4iake271f.properties b/integration-tests/testData/test_scu_microscopy/grte5q85rsp3b147p4iake271f.properties
index 6bac2809320b27fda03c11efbd2e2f3d6014b34a..d48221be2155a405c7ddf2e99a0b810dc0ab29ad 100644
--- a/integration-tests/testData/test_scu_microscopy/grte5q85rsp3b147p4iake271f.properties
+++ b/integration-tests/testData/test_scu_microscopy/grte5q85rsp3b147p4iake271f.properties
@@ -3,5 +3,5 @@ number-of-additional-data-sets = 1
 number-of-experiments = 1
 number-of-samples = 1
 registration-timeout-in-minutes = 4
-thumbnail-generation-time-in-seconds = 4
-registration-time-in-seconds = 12
+thumbnail-generation-time-in-seconds = 10
+registration-time-in-seconds = 20
diff --git a/integration-tests/testData/test_scu_microscopy/ngo4lstjmgl0dsgn1ir07o48fi.properties b/integration-tests/testData/test_scu_microscopy/ngo4lstjmgl0dsgn1ir07o48fi.properties
index 043c860e5f390bac48d6a4ec60e5d38db402bd19..d48221be2155a405c7ddf2e99a0b810dc0ab29ad 100644
--- a/integration-tests/testData/test_scu_microscopy/ngo4lstjmgl0dsgn1ir07o48fi.properties
+++ b/integration-tests/testData/test_scu_microscopy/ngo4lstjmgl0dsgn1ir07o48fi.properties
@@ -3,5 +3,5 @@ number-of-additional-data-sets = 1
 number-of-experiments = 1
 number-of-samples = 1
 registration-timeout-in-minutes = 4
-thumbnail-generation-time-in-seconds = 2
-registration-time-in-seconds = 4
+thumbnail-generation-time-in-seconds = 10
+registration-time-in-seconds = 20
diff --git a/integration-tests/testData/test_scu_microscopy/ofn7lg3ee5chvskbgm7nf3drr0.properties b/integration-tests/testData/test_scu_microscopy/ofn7lg3ee5chvskbgm7nf3drr0.properties
index 8cd75040bc7e3347b44b60d4cb1764a8a6f0f7bf..d48221be2155a405c7ddf2e99a0b810dc0ab29ad 100644
--- a/integration-tests/testData/test_scu_microscopy/ofn7lg3ee5chvskbgm7nf3drr0.properties
+++ b/integration-tests/testData/test_scu_microscopy/ofn7lg3ee5chvskbgm7nf3drr0.properties
@@ -3,5 +3,5 @@ number-of-additional-data-sets = 1
 number-of-experiments = 1
 number-of-samples = 1
 registration-timeout-in-minutes = 4
-thumbnail-generation-time-in-seconds = 8
-registration-time-in-seconds = 16
+thumbnail-generation-time-in-seconds = 10
+registration-time-in-seconds = 20
diff --git a/integration-tests/testData/test_scu_microscopy/okn3scc5tmhk199m6qk80d20op.properties b/integration-tests/testData/test_scu_microscopy/okn3scc5tmhk199m6qk80d20op.properties
index a3e4eb43898347d691ed4d0632c7df205676b3ee..e1197556a1ad32561ca3bfd6050ae4ce69c3ba17 100644
--- a/integration-tests/testData/test_scu_microscopy/okn3scc5tmhk199m6qk80d20op.properties
+++ b/integration-tests/testData/test_scu_microscopy/okn3scc5tmhk199m6qk80d20op.properties
@@ -4,4 +4,4 @@ number-of-experiments = 1
 number-of-samples = 1
 registration-timeout-in-minutes = 4
 thumbnail-generation-time-in-seconds = 10
-registration-time-in-seconds = 16
+registration-time-in-seconds = 20
diff --git a/integration-tests/testData/test_scu_microscopy/ov0kc84578p8fa04t6t0g5dk8c.properties b/integration-tests/testData/test_scu_microscopy/ov0kc84578p8fa04t6t0g5dk8c.properties
index 7baa1fa07762af3629bdad91e4417e9de7b6b3e5..e1197556a1ad32561ca3bfd6050ae4ce69c3ba17 100644
--- a/integration-tests/testData/test_scu_microscopy/ov0kc84578p8fa04t6t0g5dk8c.properties
+++ b/integration-tests/testData/test_scu_microscopy/ov0kc84578p8fa04t6t0g5dk8c.properties
@@ -3,5 +3,5 @@ number-of-additional-data-sets = 1
 number-of-experiments = 1
 number-of-samples = 1
 registration-timeout-in-minutes = 4
-thumbnail-generation-time-in-seconds = 8
-registration-time-in-seconds = 14
+thumbnail-generation-time-in-seconds = 10
+registration-time-in-seconds = 20
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
index ea579d36f059eb518e27d25d53963daa7b322c24..64a1bfc7b32d847c222ab0f2ada9240bd79a53b2 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/common.js
@@ -35,6 +35,7 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 		this.PersonCreation = dtos.PersonCreation;
 		this.Role = require('as/dto/roleassignment/Role');
 		this.RoleLevel = require('as/dto/roleassignment/RoleLevel');
+		this.DataType = require('as/dto/property/DataType');
 		this.SemanticAnnotationCreation = dtos.SemanticAnnotationCreation;
 		this.DataSetCreation = dtos.DataSetCreation;
 		this.FullDataSetCreation = dtos.FullDataSetCreation;
@@ -162,6 +163,7 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 		this.SampleTypeCreation = dtos.SampleTypeCreation;
 		this.DataSetTypeCreation = dtos.DataSetTypeCreation;
 		this.MaterialTypeCreation = dtos.MaterialTypeCreation;
+		this.PropertyTypeCreation = dtos.PropertyTypeCreation;
 		this.WebAppSettings = dtos.WebAppSettings;
 
 		// operations
@@ -173,6 +175,7 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 		this.GetSamplesOperation = dtos.GetSamplesOperation;
 		this.GetDataSetsOperation = dtos.GetDataSetsOperation;
 		this.GetMaterialsOperation = dtos.GetMaterialsOperation;
+		this.GetPropertyTypesOperation = dtos.GetPropertyTypesOperation;
 		this.GetVocabulariesOperation = dtos.GetVocabulariesOperation;
 		this.GetVocabularyTermsOperation = dtos.GetVocabularyTermsOperation;
 		this.GetTagsOperation = dtos.GetTagsOperation;
@@ -192,6 +195,7 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 		this.CreateDataSetTypesOperation = dtos.CreateDataSetTypesOperation;
 		this.CreateMaterialsOperation = dtos.CreateMaterialsOperation;
 		this.CreateMaterialTypesOperation = dtos.CreateMaterialTypesOperation;
+		this.CreatePropertyTypesOperation = dtos.CreatePropertyTypesOperation;
 		this.CreateVocabulariesOperation = dtos.CreateVocabulariesOperation;
 		this.CreateVocabularyTermsOperation = dtos.CreateVocabularyTermsOperation;
 		this.CreateTagsOperation = dtos.CreateTagsOperation;
@@ -439,6 +443,18 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 			});
 		}.bind(this);
 
+		this.createPropertyType = function(facade) {
+			var c = this;
+			var creation = new dtos.PropertyTypeCreation();
+			creation.setCode(c.generateId("PROPERTY_TYPE"));
+			creation.setLabel("Testing");
+			creation.setDescription("testing");
+			creation.setDataType(c.DataType.VARCHAR);
+			return facade.createPropertyTypes([ creation ]).then(function(permIds) {
+				return permIds[0];
+			});
+		}.bind(this);
+		
 		this.createVocabulary = function(facade) {
 			var c = this;
 			var creation = new dtos.VocabularyCreation();
@@ -638,6 +654,15 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 			});
 		}.bind(this);
 
+		this.findPropertyType = function(facade, id) {
+			var c = this;
+			var criteria = new c.PropertyTypeSearchCriteria();
+			criteria.withId().thatEquals(id);
+			return facade.searchPropertyTypes(criteria, c.createPropertyTypeFetchOptions()).then(function(results) {
+				return results.getObjects()[0];
+			});
+		}.bind(this);
+		
 		this.findVocabulary = function(facade, id) {
 			var c = this;
 			return facade.getVocabularies([ id ], c.createVocabularyFetchOptions()).then(function(vocabularies) {
@@ -959,6 +984,13 @@ define([ 'jquery', 'openbis', 'underscore', 'test/dtos' ], function($, defaultOp
 			return fo;
 		};
 
+		this.createPropertyTypeFetchOptions = function() {
+			var fo = new dtos.PropertyTyüeFetchOptions();
+			fo.withVocabulary();
+			fo.withMaterialType();
+			return fo;
+		};
+		
 		this.createVocabularyFetchOptions = function() {
 			var fo = new dtos.VocabularyFetchOptions();
 			fo.withTerms();
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/dtos.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/dtos.js
index 1fff83f3795018315e718e09b5e1eaaa9c5f70e0..d4988a8c7eb68330c80975c02b400d20e731f437 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/dtos.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/dtos.js
@@ -426,6 +426,11 @@ var sources = [
 	'as/dto/project/update/UpdateProjectsOperationResult',
 	
 	'as/dto/property/create/PropertyAssignmentCreation',
+	'as/dto/property/create/PropertyTypeCreation',
+	'as/dto/property/create/CreatePropertyTypesOperation',
+	'as/dto/property/create/CreatePropertyTypesOperationResult',
+	'as/dto/property/get/GetPropertyTypesOperation',
+	'as/dto/property/get/GetPropertyTypesOperationResult',
 	'as/dto/property/id/PropertyTypePermId',
 	'as/dto/property/id/PropertyAssignmentPermId',
 	'as/dto/property/fetchoptions/PropertyAssignmentFetchOptions',
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/openbis-execute-operations.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/openbis-execute-operations.js
index acafd1356d83fe14f27f768d2db21fc002a4acca..5668c4070c021a96584cdbaa9ddf5f62340e2d28 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/openbis-execute-operations.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/openbis-execute-operations.js
@@ -129,6 +129,10 @@ define([ 'jquery', 'openbis', 'test/common' ], function($, openbis, common) {
 			return this._executeCreateOperation(new c.CreateMaterialTypesOperation(creations));
 		}
 
+		this.createPropertyTypes = function(creations) {
+			return this._executeCreateOperation(new c.CreatePropertyTypesOperation(creations));
+		}
+		
 		this.createVocabularyTerms = function(creations) {
 			return this._executeCreateOperation(new c.CreateVocabularyTermsOperation(creations));
 		}
@@ -253,6 +257,10 @@ define([ 'jquery', 'openbis', 'test/common' ], function($, openbis, common) {
 			return this._executeGetOperation(new c.GetMaterialsOperation(ids, fetchOptions));
 		}
 
+		this.getPropertyTypes = function(ids, fetchOptions) {
+			return this._executeGetOperation(new c.GetPropertyTypesOperation(ids, fetchOptions));
+		}
+		
 		this.getVocabularies = function(ids, fetchOptions) {
 			return this._executeGetOperation(new c.GetVocabulariesOperation(ids, fetchOptions));
 		}
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
index 57d5e7b0ad2720848ece6554b7e88910d8f40890..fb9a6faa84a93f856b8830718fa9156412608f1a 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-create.js
@@ -450,6 +450,30 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 
 			testCreate(c, fCreate, c.findMaterialType, fCheck);
 		});
+		
+		QUnit.test("createPropertyTypes()", function(assert) {
+			var c = new common(assert, openbis);
+			var code = c.generateId("PROPERTY_TYPE");
+			
+			var fCreate = function(facade) {
+				var creation = new c.PropertyTypeCreation();
+				creation.setCode(code);
+				creation.setDescription("hello");
+				creation.setDataType(c.DataType.INTEGER);
+				creation.setLabel("Test Property Type");
+				return facade.createPropertyTypes([ creation ]);
+			}
+			
+			var fCheck = function(type) {
+				c.assertEqual(type.getCode(), code, "Type code");
+				c.assertEqual(type.getPermId().getPermId(), code, "Type perm id");
+				c.assertEqual(type.getLabel(), "Test Property Type", "Label");
+				c.assertEqual(type.getDescription(), "hello", "Description");
+				c.assertEqual(type.getDataType(), c.DataType.INTEGER, "Data type");
+			}
+			
+			testCreate(c, fCreate, c.findPropertyType, fCheck);
+		});
 
 		QUnit.test("createVocabularies()", function(assert) {
 			var c = new common(assert, openbis);
diff --git a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-get.js b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-get.js
index f295e9540249e302d20d781baf6b6562a34d8efa..7eb31d85fa634390f7fb62eb7d26c3812d818067 100644
--- a/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-get.js
+++ b/js-test/servers/common/core-plugins/tests/1/as/webapps/openbis-v3-api-test/html/test/test-get.js
@@ -273,27 +273,51 @@ define([ 'jquery', 'underscore', 'openbis', 'test/openbis-execute-operations', '
 			testGet(c, fCreate, fGet, fGetEmptyFetchOptions, fechOptionsTestConfig);
 		});
 
+		QUnit.test("getPropertyTypes()", function(assert) {
+			var c = new common(assert, openbis);
+			var fo = new c.PropertyTypeFetchOptions();
+			var fechOptionsTestConfig = getConfigForFetchOptions(fo);
+			fechOptionsTestConfig.SortBy = null;
+
+			var fCreate = function(facade) {
+				return $.when(c.createPropertyType(facade), c.createPropertyType(facade)).then(function(permId1, permId2) {
+					return [ permId1, permId2 ];
+				});
+			}
+
+			var fGet = function(facade, permIds) {
+				testFetchOptionsAssignation(c, fo, fechOptionsTestConfig);
+				return facade.getPropertyTypes(permIds, fo);
+			}
+
+			var fGetEmptyFetchOptions = function(facade, permIds) {
+				return facade.getPropertyTypes(permIds, new c.PropertyTypeFetchOptions());
+			}
+
+			testGet(c, fCreate, fGet, fGetEmptyFetchOptions, fechOptionsTestConfig);
+		});
+		
 		QUnit.test("getVocabularies()", function(assert) {
 			var c = new common(assert, openbis);
 			var fo = new c.VocabularyFetchOptions();
 			var fechOptionsTestConfig = getConfigForFetchOptions(fo);
 			fechOptionsTestConfig.SortBy = null;
-
+			
 			var fCreate = function(facade) {
 				return $.when(c.createVocabulary(facade), c.createVocabulary(facade)).then(function(permId1, permId2) {
 					return [ permId1, permId2 ];
 				});
 			}
-
+			
 			var fGet = function(facade, permIds) {
 				testFetchOptionsAssignation(c, fo, fechOptionsTestConfig);
 				return facade.getVocabularies(permIds, fo);
 			}
-
+			
 			var fGetEmptyFetchOptions = function(facade, permIds) {
 				return facade.getVocabularies(permIds, new c.VocabularyFetchOptions());
 			}
-
+			
 			testGet(c, fCreate, fGet, fGetEmptyFetchOptions, fechOptionsTestConfig);
 		});
 
diff --git a/microservice-server/build.gradle b/microservice-server/build.gradle
index 646dd1cdbfecdca95918ae4d6ebe6eea19cdf337..31097d3b24565f8e6900b88d4099481782a3e39d 100644
--- a/microservice-server/build.gradle
+++ b/microservice-server/build.gradle
@@ -6,7 +6,6 @@ task wrapper(type: Wrapper) {
 }
 
 repositories {
-    mavenCentral()
     ivy {
         ivyPattern "http://svnsis.ethz.ch/repos/cisd/ivy-repository/trunk/[organisation]/[module]/[revision]/ivy.xml"
         artifactPattern "http://svnsis.ethz.ch/repos/cisd/ivy-repository/trunk/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
diff --git a/microservice-server/gradle/wrapper/gradle-wrapper.properties b/microservice-server/gradle/wrapper/gradle-wrapper.properties
index 3bde4b663e7fae0d3df1cddeb38898f41709b1b6..2df108562a21e0116bc037aeae24a5aa9efda179 100644
--- a/microservice-server/gradle/wrapper/gradle-wrapper.properties
+++ b/microservice-server/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-bin.zip
+distributionUrl=http\://svnsis.ethz.ch/repos/cisd/ivy-repository/trunk/gradle/distribution/4.5/gradle-4.5-bin.zip
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
index 99946ad85ddb28a9c4466ed4b82701929346f39b..066fe6346b9627d19bd1095e0a97933635586c17 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
@@ -220,8 +220,15 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update.ProjectUpdate;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update.UpdateProjectsOperation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.CreatePropertyTypesOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.CreatePropertyTypesOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyAssignmentFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.get.GetPropertyTypesOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.get.GetPropertyTypesOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyAssignmentSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.SearchPropertyAssignmentsOperation;
@@ -516,6 +523,13 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
         return result.getObjectIds();
     }
 
+    @Override
+    public List<PropertyTypePermId> createPropertyTypes(String sessionToken, List<PropertyTypeCreation> newPropertyTypes)
+    {
+        CreatePropertyTypesOperationResult result = executeOperation(sessionToken, new CreatePropertyTypesOperation(newPropertyTypes));
+        return result.getObjectIds();
+    }
+
     @Override
     @Transactional
     public List<VocabularyPermId> createVocabularies(String sessionToken, List<VocabularyCreation> creations)
@@ -741,6 +755,15 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
         return result.getObjectMap();
     }
 
+    @Override
+    @Transactional(readOnly = true)
+    public Map<IPropertyTypeId, PropertyType> getPropertyTypes(String sessionToken, List<? extends IPropertyTypeId> typeIds,
+            PropertyTypeFetchOptions fetchOptions)
+    {
+        GetPropertyTypesOperationResult result = executeOperation(sessionToken, new GetPropertyTypesOperation(typeIds, fetchOptions));
+        return result.getObjectMap();
+    }
+
     @Override
     @Transactional(readOnly = true)
     public Map<IVocabularyId, Vocabulary> getVocabularies(String sessionToken, List<? extends IVocabularyId> vocabularyIds,
@@ -777,6 +800,7 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
     }
 
     @Override
+    @Transactional(readOnly = true)
     public Map<IRoleAssignmentId, RoleAssignment> getRoleAssignments(String sessionToken, List<? extends IRoleAssignmentId> ids,
             RoleAssignmentFetchOptions fetchOptions)
     {
@@ -785,6 +809,7 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
     }
 
     @Override
+    @Transactional(readOnly = true)
     public Map<IPersonId, Person> getPersons(String sessionToken, List<? extends IPersonId> ids, PersonFetchOptions fetchOptions)
     {
         GetPersonsOperationResult result = executeOperation(sessionToken, new GetPersonsOperation(ids, fetchOptions));
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
index 0465095cd8792fdac117da77d8ab17232c25b5c7..7aa5e6ba88544cbbe6ebc671fa982a9b5df855a4 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiLogger.java
@@ -120,8 +120,11 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCrit
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update.ProjectUpdate;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyAssignmentFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyAssignmentSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.roleassignment.RoleAssignment;
@@ -308,6 +311,13 @@ public class ApplicationServerApiLogger extends AbstractServerLogger implements
         return null;
     }
 
+    @Override
+    public List<PropertyTypePermId> createPropertyTypes(String sessionToken, List<PropertyTypeCreation> newPropertyTypes)
+    {
+        logAccess(sessionToken, "create-property-types", "NEW_PROPERTY_TYPES(%s)", abbreviate(newPropertyTypes));
+        return null;
+    }
+
     @Override
     public List<VocabularyPermId> createVocabularies(String sessionToken, List<VocabularyCreation> newVocabularies)
     {
@@ -505,6 +515,14 @@ public class ApplicationServerApiLogger extends AbstractServerLogger implements
         return null;
     }
 
+    @Override
+    public Map<IPropertyTypeId, PropertyType> getPropertyTypes(String sessionToken, List<? extends IPropertyTypeId> typeIds,
+            PropertyTypeFetchOptions fetchOptions)
+    {
+        logAccess(sessionToken, "get-property-types", "PROPERTY_TYPE_IDS(%s) FETCH_OPTIONS(%s)", abbreviate(typeIds), fetchOptions);
+        return null;
+    }
+
     @Override
     public Map<IVocabularyId, Vocabulary> getVocabularies(String sessionToken, List<? extends IVocabularyId> vocabularyIds,
             VocabularyFetchOptions fetchOptions)
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/operation/OperationsExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/operation/OperationsExecutor.java
index 8c17409b7eba5cc5dacff3e0dfd7316a386f94bf..662c18b6cb6d2b4f060a57bbc2c0292d16f6d200 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/operation/OperationsExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/operation/OperationsExecutor.java
@@ -87,6 +87,8 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.project.IDeleteProje
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.project.IGetProjectsOperationExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.project.ISearchProjectsOperationExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.project.IUpdateProjectsOperationExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.property.ICreatePropertyTypesOperationExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.property.IGetPropertyTypesOperationExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.property.ISearchPropertyAssignmentsOperationExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.property.ISearchPropertyTypesOperationExecutor;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.roleassignment.ICreateRoleAssignmentsOperationExecutor;
@@ -220,6 +222,9 @@ public class OperationsExecutor implements IOperationsExecutor
     @Autowired
     private ICreateSemanticAnnotationsOperationExecutor createSemanticAnnotationsExecutor;
 
+    @Autowired
+    private ICreatePropertyTypesOperationExecutor createPropertyTypesExecutor;
+    
     @Autowired
     private ICreateVocabulariesOperationExecutor createVocabulariesExecutor;
     
@@ -341,8 +346,11 @@ public class OperationsExecutor implements IOperationsExecutor
     private IGetPersonsOperationExecutor getPersonsExecutor;
     
     @Autowired
-    private IGetVocabulariesOperationExecutor getVocabulariesExecutor;
+    private IGetPropertyTypesOperationExecutor getPropertyTypesExecutor;
 
+    @Autowired
+    private IGetVocabulariesOperationExecutor getVocabulariesExecutor;
+    
     @Autowired
     private IGetVocabularyTermsOperationExecutor getVocabularyTermsExecutor;
     
@@ -543,6 +551,7 @@ public class OperationsExecutor implements IOperationsExecutor
         resultMap.putAll(getAuthorizationGroupsExecutor.execute(context, operations));
         resultMap.putAll(getRoleAssignmentsExecutor.execute(context, operations));
         resultMap.putAll(getPersonsExecutor.execute(context, operations));
+        resultMap.putAll(getPropertyTypesExecutor.execute(context, operations));
         resultMap.putAll(getVocabulariesExecutor.execute(context, operations));
         resultMap.putAll(getVocabularyTermsExecutor.execute(context, operations));
         resultMap.putAll(getExternalDmsExecutor.execute(context, operations));
@@ -588,6 +597,7 @@ public class OperationsExecutor implements IOperationsExecutor
         resultMap.putAll(createPersonsExecutor.execute(context, operations));
         resultMap.putAll(createVocabulariesExecutor.execute(context, operations));
         resultMap.putAll(createVocabularyTermsExecutor.execute(context, operations));
+        resultMap.putAll(createPropertyTypesExecutor.execute(context, operations));
         resultMap.putAll(createExperimentTypesExecutor.execute(context, operations));
         resultMap.putAll(createSampleTypesExecutor.execute(context, operations));
         resultMap.putAll(createDataSetTypesExecutor.execute(context, operations));
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypeExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..35a6f376f47de2811bfec3c2caf1236f9ab570d4
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypeExecutor.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.IObjectId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.EntityTypePermId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.IEntityTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.id.IVocabularyId;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.context.IProgress;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.IOperationContext;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.AbstractCreateEntityExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.IMapEntityTypeByIdExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.vocabulary.IMapVocabularyByIdExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.common.batch.CollectionBatch;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.common.batch.CollectionBatchProcessor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.common.batch.MapBatch;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.entity.progress.CreateProgress;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.DataAccessExceptionTranslator;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.shared.dto.DataTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE;
+import ch.systemsx.cisd.openbis.generic.shared.util.XmlUtils;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class CreatePropertyTypeExecutor
+        extends AbstractCreateEntityExecutor<PropertyTypeCreation, PropertyTypePE, PropertyTypePermId>
+        implements ICreatePropertyTypeExecutor
+{
+    @Autowired
+    private IDAOFactory daoFactory;
+
+    @Autowired
+    private IMapVocabularyByIdExecutor mapVocabularyByIdExecutor;
+
+    @Autowired
+    private IMapEntityTypeByIdExecutor mapMaterialTypeByIdExecutor;
+
+    @Autowired
+    private IPropertyTypeAuthorizationExecutor authorizationExecutor;
+
+    @Override
+    protected IObjectId getId(PropertyTypePE entity)
+    {
+        return new PropertyTypePermId(entity.getCode());
+    }
+
+    @Override
+    protected PropertyTypePermId createPermId(IOperationContext context, PropertyTypePE entity)
+    {
+        return new PropertyTypePermId(entity.getCode());
+    }
+
+    @Override
+    protected void checkData(IOperationContext context, PropertyTypeCreation creation)
+    {
+        if (StringUtils.isEmpty(creation.getCode()))
+        {
+            throw new UserFailureException("Code cannot be empty.");
+        }
+        if (StringUtils.isEmpty(creation.getLabel()))
+        {
+            throw new UserFailureException("Label cannot be empty.");
+        }
+        if (StringUtils.isEmpty(creation.getDescription()))
+        {
+            throw new UserFailureException("Description cannot be empty.");
+        }
+        DataType dataType = creation.getDataType();
+        if (dataType == null)
+        {
+            throw new UserFailureException("Data type not specified.");
+        }
+        if (dataType == DataType.CONTROLLEDVOCABULARY && creation.getVocabularyId() == null)
+        {
+            throw new UserFailureException("Data type has been specified as " 
+                    + DataType.CONTROLLEDVOCABULARY + " but vocabulary id is missing.");
+        }
+        if (creation.getVocabularyId() != null && dataType != DataType.CONTROLLEDVOCABULARY)
+        {
+            throw new UserFailureException("Vocabulary id has been specified but data type is " + dataType + ".");
+        }
+        IEntityTypeId materialTypeId = creation.getMaterialTypeId();
+        if (materialTypeId != null)
+        {
+            if (dataType != DataType.MATERIAL)
+            {
+                throw new UserFailureException("Material type id has been specified but data type is " + dataType + ".");
+            }
+            if (materialTypeId instanceof EntityTypePermId)
+            {
+                EntityTypePermId permId = (EntityTypePermId) materialTypeId;
+                if (permId.getEntityKind() != EntityKind.MATERIAL)
+                {
+                    throw new UserFailureException("Specified entity type id (" + materialTypeId + ") is not a " 
+                            + EntityKind.MATERIAL + " type.");
+                }
+            }
+        }
+        XmlUtils.validateXML(creation.getSchema(), "XML Schema", XmlUtils.XML_SCHEMA_XSD_FILE_RESOURCE);
+        XmlUtils.validateXML(creation.getTransformation(), "XSLT", XmlUtils.XSLT_XSD_FILE_RESOURCE);
+    }
+
+    @Override
+    protected void checkAccess(IOperationContext context)
+    {
+        authorizationExecutor.canCreate(context);
+    }
+
+    @Override
+    protected void checkAccess(IOperationContext context, PropertyTypePE entity)
+    {
+    }
+
+    @Override
+    protected List<PropertyTypePE> createEntities(IOperationContext context, CollectionBatch<PropertyTypeCreation> batch)
+    {
+        List<DataTypePE> dataTypes = daoFactory.getPropertyTypeDAO().listDataTypes();
+        Map<String, DataTypePE> map = dataTypes.stream().collect(
+                Collectors.toMap(t -> t.getCode().toString(), Function.identity()));
+        List<PropertyTypePE> propertyTypes = new ArrayList<>();
+        PersonPE person = context.getSession().tryGetPerson();
+        new CollectionBatchProcessor<PropertyTypeCreation>(context, batch)
+            {
+                @Override
+                public void process(PropertyTypeCreation creation)
+                {
+                    PropertyTypePE propertyType = new PropertyTypePE();
+                    propertyType.setCode(creation.getCode());
+                    propertyType.setDescription(creation.getDescription());
+                    propertyType.setLabel(creation.getLabel());
+                    propertyType.setType(map.get(creation.getDataType().toString()));
+                    propertyType.setInternalNamespace(Boolean.TRUE.equals(creation.isInternalNameSpace()));
+                    propertyType.setManagedInternally(Boolean.TRUE.equals(creation.isManagedInternally()));
+                    propertyType.setRegistrator(person);
+                    propertyType.setSchema(creation.getSchema());
+                    propertyType.setTransformation(creation.getTransformation());
+                    propertyTypes.add(propertyType);
+                }
+
+                @Override
+                public IProgress createProgress(PropertyTypeCreation object, int objectIndex, int totalObjectCount)
+                {
+                    return new CreateProgress(object, objectIndex, totalObjectCount);
+                }
+            };
+        return propertyTypes;
+    }
+
+    @Override
+    protected void updateBatch(IOperationContext context, MapBatch<PropertyTypeCreation, PropertyTypePE> batch)
+    {
+        injectVocabularies(context, batch);
+        injectMaterialTypes(context, batch);
+    }
+
+    private void injectVocabularies(IOperationContext context, MapBatch<PropertyTypeCreation, PropertyTypePE> batch)
+    {
+        Set<IVocabularyId> vocabularyIds = extract(batch, PropertyTypeCreation::getVocabularyId);
+        Map<IVocabularyId, VocabularyPE> vocabulariesById = mapVocabularyByIdExecutor.map(context, vocabularyIds);
+        for (Entry<PropertyTypeCreation, PropertyTypePE> entry : batch.getObjects().entrySet())
+        {
+            PropertyTypeCreation creation = entry.getKey();
+            PropertyTypePE propertyType = entry.getValue();
+            IVocabularyId vocabularyId = creation.getVocabularyId();
+            if (vocabularyId != null)
+            {
+                propertyType.setVocabulary(vocabulariesById.get(vocabularyId));
+            }
+        }
+    }
+
+    private void injectMaterialTypes(IOperationContext context, MapBatch<PropertyTypeCreation, PropertyTypePE> batch)
+    {
+        Set<IEntityTypeId> typeIds = extract(batch, PropertyTypeCreation::getMaterialTypeId);
+        Map<IEntityTypeId, EntityTypePE> materialTypesById = mapMaterialTypeByIdExecutor.map(context, 
+                ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.MATERIAL, typeIds);
+        for (Entry<PropertyTypeCreation, PropertyTypePE> entry : batch.getObjects().entrySet())
+        {
+            PropertyTypeCreation creation = entry.getKey();
+            PropertyTypePE propertyType = entry.getValue();
+            IEntityTypeId materialTypeId = creation.getMaterialTypeId();
+            if (materialTypeId != null)
+            {
+                propertyType.setMaterialType((MaterialTypePE) materialTypesById.get(materialTypeId));
+            }
+        }
+    }
+    
+    private <T> Set<T> extract(MapBatch<PropertyTypeCreation, PropertyTypePE> batch, Function<PropertyTypeCreation, T> mapper)
+    {
+        return batch.getObjects().keySet().stream()
+                .filter(c -> mapper.apply(c) != null).map(mapper).collect(Collectors.toSet());
+    }
+    
+    @Override
+    protected List<PropertyTypePE> list(IOperationContext context, Collection<Long> ids)
+    {
+        return daoFactory.getPropertyTypeDAO().listAllPropertyTypes();
+    }
+
+    @Override
+    protected void save(IOperationContext context, List<PropertyTypePE> entities, boolean clearCache)
+    {
+        for (PropertyTypePE propertyType : entities)
+        {
+            daoFactory.getPropertyTypeDAO().createPropertyType(propertyType);
+        }
+    }
+
+    @Override
+    protected void updateAll(IOperationContext context, MapBatch<PropertyTypeCreation, PropertyTypePE> batch)
+    {
+    }
+    
+    @Override
+    protected void handleException(DataAccessException e)
+    {
+        DataAccessExceptionTranslator.throwException(e, "property type", null);
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypesOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypesOperationExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b6681fd2ea1d786fc7c1332e531326611daa064
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/CreatePropertyTypesOperationExecutor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.CreateObjectsOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.CreateObjectsOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.CreatePropertyTypesOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.CreatePropertyTypesOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.IOperationContext;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.create.CreateObjectsOperationExecutor;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class CreatePropertyTypesOperationExecutor
+        extends CreateObjectsOperationExecutor<PropertyTypeCreation, PropertyTypePermId>
+        implements ICreatePropertyTypesOperationExecutor
+{
+    @Autowired
+    private ICreatePropertyTypeExecutor executor;
+
+    @Override
+    protected Class<? extends CreateObjectsOperation<PropertyTypeCreation>> getOperationClass()
+    {
+        return CreatePropertyTypesOperation.class;
+    }
+
+    @Override
+    protected CreateObjectsOperationResult<PropertyTypePermId> doExecute(IOperationContext context,
+            CreateObjectsOperation<PropertyTypeCreation> operation)
+    {
+        return new CreatePropertyTypesOperationResult(executor.create(context, operation.getCreations()));
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/GetPropertyTypesOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/GetPropertyTypesOperationExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..97097aa797af72d7676a17de670949f68024d875
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/GetPropertyTypesOperationExecutor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetObjectsOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetObjectsOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.get.GetPropertyTypesOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.get.GetPropertyTypesOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.get.GetObjectsPEOperationExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.get.IMapObjectByIdExecutor;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.ITranslator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.property.IPropertyTypeTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+@Component
+public class GetPropertyTypesOperationExecutor
+        extends GetObjectsPEOperationExecutor<IPropertyTypeId, PropertyTypePE, PropertyType, PropertyTypeFetchOptions>
+        implements IGetPropertyTypesOperationExecutor
+{
+    @Autowired
+    private IMapPropertyTypeByIdExecutor mapExecutor;
+    
+    @Autowired
+    private IPropertyTypeTranslator translator;
+
+    @Override
+    protected IMapObjectByIdExecutor<IPropertyTypeId, PropertyTypePE> getExecutor()
+    {
+        return mapExecutor;
+    }
+
+    @Override
+    protected ITranslator<Long, PropertyType, PropertyTypeFetchOptions> getTranslator()
+    {
+        return translator;
+    }
+
+    @Override
+    protected GetObjectsOperationResult<IPropertyTypeId, PropertyType> getOperationResult(Map<IPropertyTypeId, PropertyType> objectMap)
+    {
+        return new GetPropertyTypesOperationResult(objectMap);
+    }
+
+    @Override
+    protected Class<? extends GetObjectsOperation<IPropertyTypeId, PropertyTypeFetchOptions>> getOperationClass()
+    {
+        return GetPropertyTypesOperation.class;
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypeExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypeExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..66c58258b571130a9a4464b70a8be13e867b4a05
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypeExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.entity.ICreateEntityExecutor;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+public interface ICreatePropertyTypeExecutor extends ICreateEntityExecutor<PropertyTypeCreation, PropertyTypePermId>
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypesOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypesOperationExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..f727c4e3f26ab0bd97e690e102824580bab7344d
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/ICreatePropertyTypesOperationExecutor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.IOperationExecutor;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+public interface ICreatePropertyTypesOperationExecutor extends IOperationExecutor
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IGetPropertyTypesOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IGetPropertyTypesOperationExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0390fbd5a449b53761596f53279a105f053e4e3
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IGetPropertyTypesOperationExecutor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.executor.property;
+
+import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.common.IOperationExecutor;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+public interface IGetPropertyTypesOperationExecutor extends IOperationExecutor
+{
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IPropertyTypeAuthorizationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IPropertyTypeAuthorizationExecutor.java
index 009bbe1915dfaa82b9f6755c27eb0e53a5bf1a39..b148bd599f159af8e15e346cf52430c7b67c6466 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IPropertyTypeAuthorizationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/IPropertyTypeAuthorizationExecutor.java
@@ -29,4 +29,6 @@ public interface IPropertyTypeAuthorizationExecutor extends IObjectAuthorization
 
     void canSearch(IOperationContext context);
 
+    void canCreate(IOperationContext context);
+
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/PropertyTypeAuthorizationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/PropertyTypeAuthorizationExecutor.java
index 5bc4b28670641675bcf75f4765fe7d9dc648c677..163f86d9fae3adbe44ee7da7f57ca7581c55810d 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/PropertyTypeAuthorizationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/PropertyTypeAuthorizationExecutor.java
@@ -44,4 +44,11 @@ public class PropertyTypeAuthorizationExecutor implements IPropertyTypeAuthoriza
     {
     }
 
+    @Override
+    @RolesAllowed(RoleWithHierarchy.INSTANCE_ADMIN)
+    @Capability("CREATE_PROPERTY_TYPE")
+    public void canCreate(IOperationContext context)
+    {
+    }
+
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/property/PropertyTypeComparatorFactory.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/property/PropertyTypeComparatorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef68061cd5891c649d89942ebe5f7949aa52b019
--- /dev/null
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/property/PropertyTypeComparatorFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.server.asapi.v3.helper.property;
+
+import java.util.Comparator;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeSortOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.fetchoptions.VocabularySortOptions;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.sort.CodeComparator;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.sort.ComparatorFactory;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+public class PropertyTypeComparatorFactory extends ComparatorFactory
+{
+
+    @Override
+    public boolean accepts(Class<?> sortOptionsClass)
+    {
+        return PropertyTypeSortOptions.class.isAssignableFrom(sortOptionsClass);
+    }
+
+    @Override
+    public Comparator<PropertyType> getComparator(String field)
+    {
+        if (VocabularySortOptions.CODE.equals(field))
+        {
+            return new CodeComparator<PropertyType>();
+        } else
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public Comparator<PropertyType> getDefaultComparator()
+    {
+        return new CodeComparator<PropertyType>();
+    }
+
+}
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/sort/ComparatorFactory.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/sort/ComparatorFactory.java
index 70b7236e69aa7ce3d4384b9f14125102575dafe6..3a8e1b7b56ce24b16a80c4348fd16c24fce4e17c 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/sort/ComparatorFactory.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/helper/sort/ComparatorFactory.java
@@ -27,6 +27,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.globalsearch.GlobalSea
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.material.MaterialComparatorFactory;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.project.ProjectComparatorFactory;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.property.PropertyAssignmentComparatorFactory;
+import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.property.PropertyTypeComparatorFactory;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.sample.SampleComparatorFactory;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.space.SpaceComparatorFactory;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.helper.tag.TagComparatorFactory;
@@ -55,6 +56,7 @@ public abstract class ComparatorFactory
         factories.add(new SampleComparatorFactory());
         factories.add(new DataSetComparatorFactory());
         factories.add(new MaterialComparatorFactory());
+        factories.add(new PropertyTypeComparatorFactory());
         factories.add(new PropertyAssignmentComparatorFactory());
     }
 
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTypeTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTypeTranslator.java
index 4c9cee1ca248ca5e004cd8d48ef0dad1f85769f8..5e582a9d397608e6f1fddcec401d4f80c8784529 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTypeTranslator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTypeTranslator.java
@@ -30,6 +30,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.semanticannotation.SemanticAnnot
 import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.AbstractCachingTranslator;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.TranslationContext;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.translator.TranslationResults;
+import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter;
 
 /**
  * @author pkupczyk
@@ -105,7 +106,8 @@ public class PropertyTypeTranslator extends AbstractCachingTranslator<Long, Prop
         PropertyTypeRecord baseRecord = relations.get(IPropertyTypeBaseTranslator.class, typeId);
 
         result.setCode(baseRecord.code);
-        result.setPermId(new PropertyTypePermId(baseRecord.code));
+        String permId = CodeConverter.tryToBusinessLayer(baseRecord.code, baseRecord.is_internal_namespace);
+        result.setPermId(new PropertyTypePermId(permId));
         result.setLabel(baseRecord.label);
         result.setDescription(baseRecord.description);
         result.setDataType(DataType.valueOf(baseRecord.data_type));
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/PropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/PropertyTypeBO.java
index 2aa6d30377cab3286ae8d39ec81dd193a4630511..0d4c9562f311516d8aa51648214c1e0771a31aa2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/PropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/PropertyTypeBO.java
@@ -18,16 +18,12 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo;
 
 import java.util.Collections;
 
-import javax.xml.validation.Schema;
-
 import org.springframework.dao.DataAccessException;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.dao.DataRetrievalFailureException;
-import org.w3c.dom.Document;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.shared.basic.string.StringUtils;
-import ch.systemsx.cisd.common.xml.XMLInfraStructure;
 import ch.systemsx.cisd.openbis.generic.server.business.IRelationshipService;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.util.DataSetTypeWithoutExperimentChecker;
 import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
@@ -124,27 +120,8 @@ public final class PropertyTypeBO extends VocabularyBO implements IPropertyTypeB
 
     private void validateXmlDocumentValues()
     {
-        validateXML(propertyTypePE.getSchema(), "XML Schema", XmlUtils.XML_SCHEMA_XSD_FILE_RESOURCE);
-        validateXML(propertyTypePE.getTransformation(), "XSLT", XmlUtils.XSLT_XSD_FILE_RESOURCE);
-    }
-
-    private static void validateXML(String xmlValue, String xmlName, String schemaFilePath)
-    {
-        if (StringUtils.isBlank(xmlValue))
-        {
-            return;
-        }
-
-        Document document = XmlUtils.parseXmlDocument(xmlValue);
-        Schema schema = XMLInfraStructure.createSchema(schemaFilePath);
-        try
-        {
-            XmlUtils.validate(document, schema);
-        } catch (Exception e)
-        {
-            throw UserFailureException.fromTemplate("Provided %s isn't valid. %s", xmlName,
-                    e.getMessage());
-        }
+        XmlUtils.validateXML(propertyTypePE.getSchema(), "XML Schema", XmlUtils.XML_SCHEMA_XSD_FILE_RESOURCE);
+        XmlUtils.validateXML(propertyTypePE.getTransformation(), "XSLT", XmlUtils.XSLT_XSD_FILE_RESOURCE);
     }
 
     private MaterialTypePE tryGetMaterialType(MaterialType materialType)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/XmlUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/XmlUtils.java
index 6afa1649118219160275d563f7e5b96fe3abc4de..eaaff27a0c35620821caaa2a02c9eae2b43da51a 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/XmlUtils.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/XmlUtils.java
@@ -43,6 +43,7 @@ import org.xml.sax.SAXException;
 
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.shared.basic.string.StringUtils;
 import ch.systemsx.cisd.common.xml.XMLInfraStructure;
 
 /**
@@ -181,4 +182,22 @@ public class XmlUtils
             throw CheckedExceptionTunnel.wrapIfNecessary(ex);
         }
     }
+
+    public static void validateXML(String xmlValue, String xmlName, String schemaFilePath)
+    {
+        if (StringUtils.isBlank(xmlValue))
+        {
+            return;
+        }
+    
+        Document document = parseXmlDocument(xmlValue);
+        Schema schema = XMLInfraStructure.createSchema(schemaFilePath);
+        try
+        {
+            validate(document, schema);
+        } catch (Exception e)
+        {
+            throw UserFailureException.fromTemplate("Provided %s isn't valid. %s", xmlName, e.getMessage());
+        }
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperation.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperation.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8457dd7b2be4d994a0cc326dfbe74526090e14d
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperation.js
@@ -0,0 +1,13 @@
+define([ "stjs", "as/dto/common/create/CreateObjectsOperation" ], function(stjs, CreateObjectsOperation) {
+    var CreatePropertyTypesOperation = function(creations) {
+        CreateObjectsOperation.call(this, creations);
+    };
+    stjs.extend(CreatePropertyTypesOperation, CreateObjectsOperation, [ CreateObjectsOperation ], function(constructor, prototype) {
+        prototype['@type'] = 'as.dto.property.create.CreatePropertyTypesOperation';
+        prototype.getMessage = function() {
+            return "CreatePropertyTypesOperation";
+        };
+    }, {});
+    return CreatePropertyTypesOperation;
+})
+
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperationResult.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperationResult.js
new file mode 100644
index 0000000000000000000000000000000000000000..983ee77711db75575036f82a3ad4b0b26d0b96b9
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/CreatePropertyTypesOperationResult.js
@@ -0,0 +1,12 @@
+define([ "stjs", "as/dto/common/create/CreateObjectsOperationResult" ], function(stjs, CreateObjectsOperationResult) {
+	var CreatePropertyTypesOperationResult = function(objectIds) {
+		CreateObjectsOperationResult.call(this, objectIds);
+	};
+	stjs.extend(CreatePropertyTypesOperationResult, CreateObjectsOperationResult, [ CreateObjectsOperationResult ], function(constructor, prototype) {
+		prototype['@type'] = 'as.dto.property.create.CreatePropertyTypesOperationResult';
+		prototype.getMessage = function() {
+			return "CreatePropertyTypesOperationResult";
+		};
+	}, {});
+	return CreatePropertyTypesOperationResult;
+})
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/PropertyTypeCreation.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/PropertyTypeCreation.js
new file mode 100644
index 0000000000000000000000000000000000000000..009cc4f4a27bd430eaa592b89c2dec3539102548
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/create/PropertyTypeCreation.js
@@ -0,0 +1,84 @@
+define([ "stjs" ], function(stjs) {
+	var PropertyTypeCreation = function() {
+	};
+	stjs.extend(PropertyTypeCreation, null, [], function(constructor, prototype) {
+		prototype['@type'] = 'as.dto.property.create.PropertyTypeCreation';
+		constructor.serialVersionUID = 1;
+		prototype.code = null;
+		prototype.label = null;
+		prototype.description = null;
+		prototype.managedInternally = null;
+		prototype.internalNameSpace = null;
+		prototype.dataType = null;
+		prototype.vocabularyId = null;
+		prototype.materialTypeId = null;
+		prototype.schema = null;
+		prototype.transformation = null;
+
+		prototype.getCode = function() {
+			return this.code;
+		};
+		prototype.setCode = function(code) {
+			this.code = code;
+		};
+		prototype.getLabel = function() {
+			return this.label;
+		};
+		prototype.setLabel = function(label) {
+			this.label = label;
+		};
+		prototype.getDescription = function() {
+			return this.description;
+		};
+		prototype.setDescription = function(description) {
+			this.description = description;
+		};
+		prototype.isManagedInternally = function() {
+			return this.managedInternally;
+		};
+		prototype.setManagedInternally = function(managedInternally) {
+			this.managedInternally = managedInternally;
+		};
+		prototype.isInternalNameSpace = function() {
+			return this.internalNameSpace;
+		};
+		prototype.setInternalNameSpace = function(internalNameSpace) {
+			this.internalNameSpace = internalNameSpace;
+		};
+		prototype.getDataType = function() {
+			return this.dataType;
+		};
+		prototype.setDataType = function(dataType) {
+			this.dataType = dataType;
+		};
+		prototype.getVocabularyId = function() {
+			return this.vocabularyId;
+		};
+		prototype.setVocabularyId = function(vocabularyId) {
+			this.vocabularyId = vocabularyId;
+		};
+		prototype.getMaterialTypeId = function() {
+			return this.materialTypeId;
+		};
+		prototype.setMaterialTypeId = function(materialTypeId) {
+			this.materialTypeId = materialTypeId;
+		};
+		prototype.getSchema = function() {
+			return this.schema;
+		};
+		prototype.setSchema = function(schema) {
+			this.schema = schema;
+		};
+		prototype.getTransformation = function() {
+			return this.transformation;
+		};
+		prototype.setTransformation = function(transformation) {
+			this.transformation = transformation;
+		};
+	}, {
+		dataType : "DataType",
+		vocabularyId : "IVocabularyId",
+		materialTypeId : "IEntityTypeId"
+	});
+	return PropertyTypeCreation;
+})
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/fetchoptions/PropertyTypeSortOptions.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/fetchoptions/PropertyTypeSortOptions.js
index fd203b1cbd0c81d5e6f883b8491e62e830ffa70d..693bb58d4fe9f985f344ff523ee6ffc3a77596cc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/fetchoptions/PropertyTypeSortOptions.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/fetchoptions/PropertyTypeSortOptions.js
@@ -2,10 +2,21 @@ define([ "require", "stjs", "as/dto/common/fetchoptions/SortOptions" ], function
 	var PropertyTypeSortOptions = function() {
 		SortOptions.call(this);
 	};
-
+	
+	var fields = {
+		CODE: "CODE",
+	};
+	
 	stjs.extend(PropertyTypeSortOptions, SortOptions, [ SortOptions ], function(constructor, prototype) {
 		prototype['@type'] = 'as.dto.property.fetchoptions.PropertyTypeSortOptions';
 		constructor.serialVersionUID = 1;
+		
+		prototype.code = function() {
+			return this.getOrCreateSorting(fields.CODE);
+		};
+		prototype.getCode = function() {
+			return this.getSorting(fields.CODE);
+		};
 	}, {});
 	return PropertyTypeSortOptions;
 })
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperation.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperation.js
new file mode 100644
index 0000000000000000000000000000000000000000..eb4b59876bca2b944abfd618078f8aa842ac1d7b
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperation.js
@@ -0,0 +1,12 @@
+define([ "stjs", "as/dto/common/get/GetObjectsOperation" ], function(stjs, GetObjectsOperation) {
+	var GetPropertyTypesOperation = function(objectIds, fetchOptions) {
+		GetObjectsOperation.call(this, objectIds, fetchOptions);
+	};
+	stjs.extend(GetPropertyTypesOperation, GetObjectsOperation, [ GetObjectsOperation ], function(constructor, prototype) {
+		prototype['@type'] = 'as.dto.property.get.GetPropertyTypesOperation';
+		prototype.getMessage = function() {
+			return "GetPropertyTypesOperation";
+		};
+	}, {});
+	return GetPropertyTypesOperation;
+})
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperationResult.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperationResult.js
new file mode 100644
index 0000000000000000000000000000000000000000..f26c02244b28717d477a787a98ee5a7e131f6c2f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/as/dto/property/get/GetPropertyTypesOperationResult.js
@@ -0,0 +1,12 @@
+define([ "stjs", "as/dto/common/get/GetObjectsOperationResult" ], function(stjs, GetObjectsOperationResult) {
+	var GetPropertyTypesOperationResult = function(objectMap) {
+		GetObjectsOperationResult.call(this, objectMap);
+	};
+	stjs.extend(GetPropertyTypesOperationResult, GetObjectsOperationResult, [ GetObjectsOperationResult ], function(constructor, prototype) {
+		prototype['@type'] = 'as.dto.property.get.GetPropertyTypesOperationResult';
+		prototype.getMessage = function() {
+			return "GetPropertyTypesOperationResult";
+		};
+	}, {});
+	return GetPropertyTypesOperationResult;
+})
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/openbis.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/openbis.js
index 9bc12600fbedbde2702f087d1f2558f2b617a15a..58d75083fe395e7451e85d035c5f025c210f36d2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/openbis.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/resources/api/v3/openbis.js
@@ -510,6 +510,21 @@ define([ 'jquery', 'util/Json', 'as/dto/datastore/search/DataStoreSearchCriteria
 			});
 		}
 
+		this.createPropertyTypes = function(creations) {
+			var thisFacade = this;
+			return thisFacade._private.ajaxRequest({
+				url : openbisUrl,
+				data : {
+					"method" : "createPropertyTypes",
+					"params" : [ thisFacade._private.sessionToken, creations ]
+				},
+				returnType : {
+					name : "List",
+					arguments : [ "PropertyTypePermId" ]
+				}
+			});
+		}
+		
 		this.createVocabularies = function(creations) {
 			var thisFacade = this;
 			return thisFacade._private.ajaxRequest({
@@ -903,6 +918,21 @@ define([ 'jquery', 'util/Json', 'as/dto/datastore/search/DataStoreSearchCriteria
 			});
 		}
 
+		this.getPropertyTypes = function(ids, fetchOptions) {
+			var thisFacade = this;
+			return thisFacade._private.ajaxRequest({
+				url : openbisUrl,
+				data : {
+					"method" : "getPropertyTypes",
+					"params" : [ thisFacade._private.sessionToken, ids, fetchOptions ]
+				},
+				returnType : {
+					name : "Map",
+					arguments : [ "IPropertyTypeId", "PropertyType" ]
+				}
+			});
+		}
+		
 		this.getVocabularies = function(ids, fetchOptions) {
 			var thisFacade = this;
 			return thisFacade._private.ajaxRequest({
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePropertyTypeTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePropertyTypeTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5029c637895f5bc3e79f7fe8cd806b54e53e063
--- /dev/null
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/CreatePropertyTypeTest.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.systemtest.asapi.v3;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.EntityKind;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.EntityTypePermId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyTypeSearchCriteria;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.id.VocabularyPermId;
+import ch.systemsx.cisd.common.action.IDelegatedAction;
+
+/**
+ * @author Franz-Josef Elmer
+ */
+public class CreatePropertyTypeTest extends AbstractTest
+{
+    private static String EXAMPLE_SCHEMA =
+            "<?xml version='1.0'?>\n"
+            + "<xs:schema targetNamespace='http://my.host.org' xmlns:xs='http://www.w3.org/2001/XMLSchema'>\n"
+            + "<xs:element name='note'>\n" 
+            + "  <xs:complexType>\n"
+            + "    <xs:sequence>\n"
+            + "      <xs:element name='to' type='xs:string'/>\n"
+            + "      <xs:element name='from' type='xs:string'/>\n"
+            + "      <xs:element name='heading' type='xs:string'/>\n"
+            + "      <xs:element name='body' type='xs:string'/>\n" 
+            + "    </xs:sequence>\n"
+            + "  </xs:complexType>\n" 
+            + "</xs:element>\n" 
+            + "</xs:schema>";
+
+
+    private static String EXAMPLE_XSLT = "<?xml version='1.0'?>\n"
+            + "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"
+            + "<xsl:output method='html'/>\n                            "
+            + "<xsl:template match='child::person'>\n                   "
+            + " <html>\n                                                "
+            + "  <head>\n                                               "
+            + "   <title>\n                                             "
+            + "    <xsl:value-of select='descendant::firstname' />\n    "
+            + "    <xsl:text> </xsl:text>\n                             "
+            + "    <xsl:value-of select='descendant::lastname' />\n     "
+            + "   </title>\n                                            "
+            + "  </head>\n                                              "
+            + "  <body>\n                                               "
+            + "   <xsl:value-of select='descendant::firstname' />\n     "
+            + "   <xsl:text> </xsl:text>\n                              "
+            + "   <xsl:value-of select='descendant::lastname' />\n      "
+            + "  </body>\n                                              "
+            + " </html>\n                                               "
+            + "</xsl:template>\n                                        "
+            + "</xsl:stylesheet>";
+
+    private static String EXAMPLE_INCORRECT_XSLT = EXAMPLE_XSLT.replaceAll("xsl:stylesheet",
+            "xsl:styleshet");
+
+    @Test
+    public void testCreateInternalNamespacePropertyType()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypeCreation creation = new PropertyTypeCreation();
+        creation.setCode("test-property");
+        creation.setDataType(DataType.REAL);
+        creation.setDescription("only for testing");
+        creation.setLabel("Test Property");
+        creation.setInternalNameSpace(true);
+        creation.setManagedInternally(true);
+
+        // When
+        List<PropertyTypePermId> ids = v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+
+        // Then
+        assertEquals(ids.toString(), "[$TEST-PROPERTY]");
+        PropertyTypeSearchCriteria searchCriteria = new PropertyTypeSearchCriteria();
+        searchCriteria.withCode().thatEquals("$" + creation.getCode().toUpperCase());
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        Map<IPropertyTypeId, PropertyType> types = v3api.getPropertyTypes(sessionToken, ids, fetchOptions);
+        PropertyType propertyType = types.get(ids.get(0));
+        assertEquals(propertyType.getCode(), creation.getCode().toUpperCase());
+        assertEquals(propertyType.getPermId(), ids.get(0));
+        assertEquals(propertyType.getDataType(), creation.getDataType());
+        assertEquals(propertyType.getDescription(), creation.getDescription());
+        assertEquals(propertyType.getLabel(), creation.getLabel());
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), creation.isInternalNameSpace());
+        assertEquals(propertyType.isManagedInternally().booleanValue(), creation.isManagedInternally());
+        assertEquals(types.size(), 1);
+
+        v3api.logout(sessionToken);
+    }
+
+    @Test
+    public void testCreateXmlPropertyType()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypeCreation creation = new PropertyTypeCreation();
+        creation.setCode("test-property");
+        creation.setDataType(DataType.XML);
+        creation.setDescription("only for testing");
+        creation.setLabel("Test Property");
+        creation.setSchema(EXAMPLE_SCHEMA);
+        creation.setTransformation(EXAMPLE_XSLT);
+
+        // When
+        List<PropertyTypePermId> ids = v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+
+        // Then
+        assertEquals(ids.toString(), "[TEST-PROPERTY]");
+        PropertyTypeSearchCriteria searchCriteria = new PropertyTypeSearchCriteria();
+        searchCriteria.withCode().thatEquals(creation.getCode().toUpperCase());
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        Map<IPropertyTypeId, PropertyType> types = v3api.getPropertyTypes(sessionToken, ids, fetchOptions);
+        PropertyType propertyType = types.get(ids.get(0));
+        assertEquals(propertyType.getCode(), creation.getCode().toUpperCase());
+        assertEquals(propertyType.getPermId(), ids.get(0));
+        assertEquals(propertyType.getDataType(), creation.getDataType());
+        assertEquals(propertyType.getDescription(), creation.getDescription());
+        assertEquals(propertyType.getLabel(), creation.getLabel());
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), false);
+        assertEquals(propertyType.isManagedInternally().booleanValue(), false);
+        assertEquals(propertyType.getSchema(), creation.getSchema());
+        assertEquals(propertyType.getTransformation(), creation.getTransformation());
+        assertEquals(types.size(), 1);
+
+        v3api.logout(sessionToken);
+    }
+
+    @Test
+    public void testCreateVocabularyPropertyType()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypeCreation creation = new PropertyTypeCreation();
+        creation.setCode("test-voca-property");
+        creation.setDataType(DataType.CONTROLLEDVOCABULARY);
+        creation.setDescription("only for testing");
+        creation.setLabel("Test Vocabulary Property");
+        creation.setVocabularyId(new VocabularyPermId("test_vocabulary"));
+
+        // When
+        List<PropertyTypePermId> ids = v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+
+        // Then
+        assertEquals(ids.toString(), "[TEST-VOCA-PROPERTY]");
+        PropertyTypeSearchCriteria searchCriteria = new PropertyTypeSearchCriteria();
+        searchCriteria.withCode().thatEquals(creation.getCode().toUpperCase());
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        fetchOptions.withVocabulary();
+        Map<IPropertyTypeId, PropertyType> types = v3api.getPropertyTypes(sessionToken, ids, fetchOptions);
+        PropertyType propertyType = types.get(ids.get(0));
+        assertEquals(propertyType.getCode(), creation.getCode().toUpperCase());
+        assertEquals(propertyType.getPermId(), ids.get(0));
+        assertEquals(propertyType.getDataType(), creation.getDataType());
+        assertEquals(propertyType.getDescription(), creation.getDescription());
+        assertEquals(propertyType.getLabel(), creation.getLabel());
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), false);
+        assertEquals(propertyType.isManagedInternally().booleanValue(), false);
+        assertEquals(propertyType.getVocabulary().getCode(), "TEST_VOCABULARY");
+        assertEquals(propertyType.getVocabulary().getDescription(), "Test vocabulary");
+        assertEquals(types.size(), 1);
+
+        v3api.logout(sessionToken);
+    }
+
+    @Test
+    public void testCreateMaterialPropertyType()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypeCreation creation = new PropertyTypeCreation();
+        creation.setCode("test-material-property");
+        creation.setDataType(DataType.MATERIAL);
+        creation.setDescription("only for testing");
+        creation.setLabel("Test Material Property");
+        creation.setMaterialTypeId(new EntityTypePermId("SIRNA", EntityKind.MATERIAL));
+
+        // When
+        List<PropertyTypePermId> ids = v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+
+        // Then
+        assertEquals(ids.toString(), "[TEST-MATERIAL-PROPERTY]");
+        PropertyTypeSearchCriteria searchCriteria = new PropertyTypeSearchCriteria();
+        searchCriteria.withCode().thatEquals(creation.getCode().toUpperCase());
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        fetchOptions.withMaterialType();
+        Map<IPropertyTypeId, PropertyType> types = v3api.getPropertyTypes(sessionToken, ids, fetchOptions);
+        PropertyType propertyType = types.get(ids.get(0));
+        assertEquals(propertyType.getCode(), creation.getCode().toUpperCase());
+        assertEquals(propertyType.getPermId(), ids.get(0));
+        assertEquals(propertyType.getDataType(), creation.getDataType());
+        assertEquals(propertyType.getDescription(), creation.getDescription());
+        assertEquals(propertyType.getLabel(), creation.getLabel());
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), false);
+        assertEquals(propertyType.isManagedInternally().booleanValue(), false);
+        assertEquals(propertyType.getMaterialType().getCode(), "SIRNA");
+        assertEquals(propertyType.getMaterialType().getDescription(), "Oligo nucleotide");
+        assertEquals(types.size(), 1);
+
+        v3api.logout(sessionToken);
+    }
+
+    @Test
+    public void testMissingCode()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setCode(null);
+        
+        assertUserFailureException(creation, "Code cannot be empty.");
+    }
+
+    @Test
+    public void testEmptyCode()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setCode("");
+
+        assertUserFailureException(creation, "Code cannot be empty.");
+    }
+
+    @Test
+    public void testMissingLabel()
+    {        
+        PropertyTypeCreation creation = createBasic();
+        creation.setLabel(null);
+
+        assertUserFailureException(creation, "Label cannot be empty.");
+    }
+    
+    @Test
+    public void testEmptyLabel()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setLabel("");
+        
+        assertUserFailureException(creation, "Label cannot be empty.");
+    }
+    
+    @Test
+    public void testMissingDescription()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDescription(null);
+        
+        assertUserFailureException(creation, "Description cannot be empty.");
+    }
+    
+    @Test
+    public void testEmptyDescription()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDescription("");
+        
+        assertUserFailureException(creation, "Description cannot be empty.");
+    }
+    
+    @Test
+    public void testMissingDataType()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(null);;
+
+        assertUserFailureException(creation, "Data type not specified.");
+    }
+
+    @Test
+    public void testVocabularyTypeMissingVocabulary()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.CONTROLLEDVOCABULARY);
+
+        assertUserFailureException(creation, "Data type has been specified as CONTROLLEDVOCABULARY but vocabulary id is missing.");
+    }
+
+    @Test
+    public void testVocabularyIdButWrongDataType()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.REAL);
+        creation.setVocabularyId(new VocabularyPermId("GENDER"));
+
+        assertUserFailureException(creation, "Vocabulary id has been specified but data type is REAL.");
+    }
+
+    @Test
+    public void testMaterialTypeIdButWrongDataType()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.REAL);
+        creation.setMaterialTypeId(new EntityTypePermId("SIRNA", EntityKind.MATERIAL));
+
+        assertUserFailureException(creation, "Material type id has been specified but data type is REAL.");
+    }
+
+    @Test
+    public void testEntityTypeIdButWrongEntityKind()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.MATERIAL);
+        creation.setMaterialTypeId(new EntityTypePermId("UNKNOWN", EntityKind.DATA_SET));
+
+        assertUserFailureException(creation, "Specified entity type id (UNKNOWN, DATA_SET) is not a MATERIAL type.");
+    }
+
+    @Test
+    public void testVocabularyTypeWithVocabularyIdAndMaterialTypeId()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.CONTROLLEDVOCABULARY);
+        creation.setVocabularyId(new VocabularyPermId("GENDER"));
+        creation.setMaterialTypeId(new EntityTypePermId("SIRNA", EntityKind.MATERIAL));
+
+        assertUserFailureException(creation, "Material type id has been specified but data type is CONTROLLEDVOCABULARY.");
+    }
+
+    @Test
+    public void testMaterialTypeWithVocabularyIdAndMaterialTypeId()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.MATERIAL);
+        creation.setVocabularyId(new VocabularyPermId("GENDER"));
+        creation.setMaterialTypeId(new EntityTypePermId("SIRNA", EntityKind.MATERIAL));
+
+        assertUserFailureException(creation, "Vocabulary id has been specified but data type is MATERIAL.");
+    }
+
+    @Test
+    public void testInvalidSchema()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.XML);
+        creation.setSchema("blabla");
+
+        assertUserFailureException(creation, "isn't a well formed XML document. Content is not allowed in prolog.");
+    }
+
+    @Test
+    public void testInvalidTransformation()
+    {
+        PropertyTypeCreation creation = createBasic();
+        creation.setDataType(DataType.XML);
+        creation.setTransformation(EXAMPLE_INCORRECT_XSLT);
+
+        assertUserFailureException(creation, "Provided XSLT isn't valid.");
+    }
+
+    @Test(dataProvider = "usersNotAllowedToCreatePropertyTypes")
+    public void testCreateWithUserCausingAuthorizationFailure(final String user)
+    {
+        assertAuthorizationFailureException(new IDelegatedAction()
+            {
+                @Override
+                public void execute()
+                {
+                    String sessionToken = v3api.login(user, PASSWORD);
+                    PropertyTypeCreation creation = new PropertyTypeCreation();
+                    creation.setCode("TEST");
+                    creation.setDescription("test");
+                    creation.setDataType(DataType.REAL);
+                    v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+                }
+            });
+    }
+
+    @DataProvider
+    Object[][] usersNotAllowedToCreatePropertyTypes()
+    {
+        return createTestUsersProvider(TEST_GROUP_ADMIN, TEST_GROUP_OBSERVER, TEST_GROUP_POWERUSER,
+                TEST_INSTANCE_OBSERVER, TEST_OBSERVER_CISD, TEST_POWER_USER_CISD, TEST_SPACE_USER);
+    }
+    
+    private PropertyTypeCreation createBasic()
+    {
+        PropertyTypeCreation creation = new PropertyTypeCreation();
+        creation.setCode("TEST");
+        creation.setLabel("Test");
+        creation.setDescription("Testing");
+        creation.setDataType(DataType.REAL);
+        return creation;
+    }
+
+    private void assertUserFailureException(PropertyTypeCreation creation, String expectedMessage)
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        assertUserFailureException(new IDelegatedAction()
+            {
+
+                @Override
+                public void execute()
+                {
+                    // When
+                    v3api.createPropertyTypes(sessionToken, Arrays.asList(creation));
+                }
+            },
+
+                // Then
+                expectedMessage);
+        v3api.logout(sessionToken);
+    }
+
+}
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetPropertyTypeTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetPropertyTypeTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c1f330e8584e66756890236797060a3ab2db054
--- /dev/null
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/GetPropertyTypeTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.systemtest.asapi.v3;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+public class GetPropertyTypeTest extends AbstractTest
+{
+    @Test
+    public void testGetSimplePropertyTypeWithBasics()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypePermId permId = new PropertyTypePermId("Description");
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        
+        // When
+        PropertyType propertyType = v3api.getPropertyTypes(sessionToken, Arrays.asList(permId), fetchOptions).get(permId);
+        
+        // Then
+        assertEquals(propertyType.getCode(), "DESCRIPTION");
+        assertEquals(propertyType.getPermId(), permId);
+        assertEquals(propertyType.getDescription(), "A Description");
+        assertEquals(propertyType.getDataType().toString(), DataType.VARCHAR.toString());
+        assertEquals(propertyType.getLabel(), "Description");
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), false);
+        assertEquals(propertyType.isManagedInternally().booleanValue(), false);
+        assertEquals(propertyType.getSchema(), null);
+        assertEquals(propertyType.getTransformation(), null);
+        
+        v3api.logout(sessionToken);
+    }
+    
+    @Test
+    public void testGetInternalNameSpacePropertyTypeWithAll()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypePermId permId = new PropertyTypePermId("$PLATE_GEOMETRY");
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        fetchOptions.withMaterialType();
+        fetchOptions.withVocabulary().withTerms().sortBy().code().desc();;
+        
+        // When
+        PropertyType propertyType = v3api.getPropertyTypes(sessionToken, Arrays.asList(permId), fetchOptions).get(permId);
+        
+        // Then
+        assertEquals(propertyType.getCode(), "PLATE_GEOMETRY");
+        assertEquals(propertyType.getPermId(), permId);
+        assertEquals(propertyType.getDescription(), "Plate Geometry");
+        assertEquals(propertyType.getDataType().toString(), DataType.CONTROLLEDVOCABULARY.toString());
+        assertEquals(propertyType.getLabel(), "Plate Geometry");
+        assertEquals(propertyType.isInternalNameSpace().booleanValue(), true);
+        assertEquals(propertyType.isManagedInternally().booleanValue(), true);
+        assertEquals(propertyType.getSchema(), null);
+        assertEquals(propertyType.getTransformation(), null);
+        assertEquals(propertyType.getMaterialType(), null);
+        assertEquals(propertyType.getVocabulary().getTerms().toString(),
+                "[VocabularyTerm 1536_WELLS_32X48, VocabularyTerm 384_WELLS_16X24, VocabularyTerm 96_WELLS_8X12]");
+
+        v3api.logout(sessionToken);
+    }
+    
+    @Test
+    public void testGetPropertyTypeWithMaterialType()
+    {
+        // Given
+        String sessionToken = v3api.login(TEST_USER, PASSWORD);
+        PropertyTypePermId permId = new PropertyTypePermId("BACTERIUM");
+        PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions();
+        fetchOptions.withMaterialType();
+        fetchOptions.withVocabulary().withTerms().sortBy().code().desc();;
+        
+        // When
+        PropertyType propertyType = v3api.getPropertyTypes(sessionToken, Arrays.asList(permId), fetchOptions).get(permId);
+        
+        // Then
+        assertEquals(propertyType.getCode(), "BACTERIUM");
+        assertEquals(propertyType.getPermId(), permId);
+        assertEquals(propertyType.getDataType().toString(), DataType.MATERIAL.toString());
+        assertEquals(propertyType.getVocabulary(), null);
+        assertEquals(propertyType.getMaterialType().getCode(), "BACTERIUM");
+        assertEquals(propertyType.getMaterialType().getDescription(), "Bacterium");
+        assertEquals(propertyType.getMaterialType().getPermId().toString(), "BACTERIUM, MATERIAL");
+
+        v3api.logout(sessionToken);
+    }
+
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
index 2687b508adb7cdf525787967e80b8fed66417cb3..cc939528d9d289f2ca0bdf35cefb2d089af5be71 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/IApplicationServerApi.java
@@ -119,8 +119,11 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCrit
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update.ProjectUpdate;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.create.PropertyTypeCreation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyAssignmentFetchOptions;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyAssignmentSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.search.PropertyTypeSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.roleassignment.RoleAssignment;
@@ -241,6 +244,8 @@ public interface IApplicationServerApi extends IRpcService
     public List<MaterialPermId> createMaterials(String sessionToken, List<MaterialCreation> newMaterials);
 
     public List<EntityTypePermId> createMaterialTypes(String sessionToken, List<MaterialTypeCreation> newMaterialTypes);
+    
+    public List<PropertyTypePermId> createPropertyTypes(String sessionToken, List<PropertyTypeCreation> newPropertyTypes);
 
     public List<VocabularyPermId> createVocabularies(String sessionToken, List<VocabularyCreation> newVocabularies);
 
@@ -312,6 +317,8 @@ public interface IApplicationServerApi extends IRpcService
 
     public Map<IMaterialId, Material> getMaterials(String sessionToken, List<? extends IMaterialId> materialIds, MaterialFetchOptions fetchOptions);
 
+    public Map<IPropertyTypeId, PropertyType> getPropertyTypes(String sessionToken, List<? extends IPropertyTypeId> typeIds, PropertyTypeFetchOptions fetchOptions);
+    
     public Map<IVocabularyId, Vocabulary> getVocabularies(String sessionToken, List<? extends IVocabularyId> vocabularyIds,
             VocabularyFetchOptions fetchOptions);
 
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperation.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperation.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d8b4851ec16897c685ae614f5dbd05ea8446ccf
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperation.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.dto.property.create;
+
+import java.util.List;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.CreateObjectsOperation;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+@JsonObject("as.dto.property.create.CreatePropertyTypesOperation")
+public class CreatePropertyTypesOperation extends CreateObjectsOperation<PropertyTypeCreation>
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private CreatePropertyTypesOperation()
+    {
+    }
+
+    public CreatePropertyTypesOperation(PropertyTypeCreation... creations)
+    {
+        super(creations);
+    }
+
+    public CreatePropertyTypesOperation(List<PropertyTypeCreation> creations)
+    {
+        super(creations);
+    }
+
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperationResult.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..c22a4001c6041f44edac0bb7f6e930a8af52199c
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/CreatePropertyTypesOperationResult.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.dto.property.create;
+
+import java.util.List;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.CreateObjectsOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.PropertyTypePermId;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+@JsonObject("as.dto.property.create.CreatePropertyTypesOperationResult")
+public class CreatePropertyTypesOperationResult extends CreateObjectsOperationResult<PropertyTypePermId>
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unused")
+    private CreatePropertyTypesOperationResult()
+    {
+    }
+
+    public CreatePropertyTypesOperationResult(List<PropertyTypePermId> objectIds)
+    {
+        super(objectIds);
+    }
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/PropertyTypeCreation.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/PropertyTypeCreation.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca63a283976898e038f05620075e6b2fcb8a3a62
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/create/PropertyTypeCreation.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.dto.property.create;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.ICreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.create.IObjectCreation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id.IEntityTypeId;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.id.IVocabularyId;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+@JsonObject("as.dto.property.create.PropertyTypeCreation")
+public class PropertyTypeCreation implements ICreation, IObjectCreation
+{
+    private static final long serialVersionUID = 1L;
+
+    @JsonProperty
+    private String code;
+    
+    @JsonProperty
+    private String label;
+    
+    @JsonProperty
+    private String description;
+    
+    @JsonProperty
+    private boolean managedInternally;
+
+    @JsonProperty
+    private boolean internalNameSpace;
+
+    @JsonProperty
+    private DataType dataType;
+    
+    @JsonProperty
+    private IVocabularyId vocabularyId;
+
+    @JsonProperty
+    private IEntityTypeId materialTypeId;
+
+    @JsonProperty
+    private String schema;
+
+    @JsonProperty
+    private String transformation;
+
+    @JsonIgnore
+    public String getCode()
+    {
+        return code;
+    }
+
+    public void setCode(String code)
+    {
+        this.code = code;
+    }
+
+    @JsonIgnore
+    public String getLabel()
+    {
+        return label;
+    }
+
+    public void setLabel(String label)
+    {
+        this.label = label;
+    }
+
+    @JsonIgnore
+    public String getDescription()
+    {
+        return description;
+    }
+
+    public void setDescription(String description)
+    {
+        this.description = description;
+    }
+
+    @JsonIgnore
+    public boolean isManagedInternally()
+    {
+        return managedInternally;
+    }
+
+    public void setManagedInternally(boolean managedInternally)
+    {
+        this.managedInternally = managedInternally;
+    }
+
+    @JsonIgnore
+    public boolean isInternalNameSpace()
+    {
+        return internalNameSpace;
+    }
+
+    public void setInternalNameSpace(boolean internalNameSpace)
+    {
+        this.internalNameSpace = internalNameSpace;
+    }
+
+    @JsonIgnore
+    public DataType getDataType()
+    {
+        return dataType;
+    }
+
+    public void setDataType(DataType dataType)
+    {
+        this.dataType = dataType;
+    }
+
+    @JsonIgnore
+    public IVocabularyId getVocabularyId()
+    {
+        return vocabularyId;
+    }
+
+    public void setVocabularyId(IVocabularyId vocabularyId)
+    {
+        this.vocabularyId = vocabularyId;
+    }
+
+    @JsonIgnore
+    public IEntityTypeId getMaterialTypeId()
+    {
+        return materialTypeId;
+    }
+
+    public void setMaterialTypeId(IEntityTypeId materialTypeId)
+    {
+        this.materialTypeId = materialTypeId;
+    }
+
+    @JsonIgnore
+    public String getSchema()
+    {
+        return schema;
+    }
+
+    public void setSchema(String schema)
+    {
+        this.schema = schema;
+    }
+
+    @JsonIgnore
+    public String getTransformation()
+    {
+        return transformation;
+    }
+
+    public void setTransformation(String transformation)
+    {
+        this.transformation = transformation;
+    }
+
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/fetchoptions/PropertyTypeSortOptions.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/fetchoptions/PropertyTypeSortOptions.java
index 9910e89f360f1d61858a9708b07e1375262f9cb0..5ae893b55b383d88561347410e098c6ae59b817e 100644
--- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/fetchoptions/PropertyTypeSortOptions.java
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/fetchoptions/PropertyTypeSortOptions.java
@@ -16,7 +16,10 @@
 
 package ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.fetchoptions.SortOrder;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
 import ch.systemsx.cisd.base.annotation.JsonObject;
 
@@ -29,4 +32,17 @@ public class PropertyTypeSortOptions extends SortOptions<PropertyType>
 
     private static final long serialVersionUID = 1L;
 
+    @JsonIgnore
+    public static final String CODE = "CODE";
+
+    public SortOrder code()
+    {
+        return getOrCreateSorting(CODE);
+    }
+
+    public SortOrder getCode()
+    {
+        return getSorting(CODE);
+    }
+
 }
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperation.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperation.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e9b12fc22e0a6a9eedda67d161b195dcf1b1518
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperation.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.dto.property.get;
+
+import java.util.List;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetObjectsOperation;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+@JsonObject("as.dto.property.get.GetPropertyTypesOperation")
+public class GetPropertyTypesOperation extends GetObjectsOperation<IPropertyTypeId, PropertyTypeFetchOptions>
+{
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unused")
+    private GetPropertyTypesOperation()
+    {
+    }
+
+    public GetPropertyTypesOperation(List<? extends IPropertyTypeId> ids, PropertyTypeFetchOptions fetchOptions)
+    {
+        super(ids, fetchOptions);
+    }
+
+}
diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperationResult.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperationResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..5aed23d9b32c97feaf01bc039c513d2f48580529
--- /dev/null
+++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/property/get/GetPropertyTypesOperationResult.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 ETH Zuerich, SIS
+ *
+ * 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.asapi.v3.dto.property.get;
+
+import java.util.Map;
+
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetObjectsOperationResult;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType;
+import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.id.IPropertyTypeId;
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author Franz-Josef Elmer
+ *
+ */
+@JsonObject("as.dto.property.get.GetPropertyTypesOperationResult")
+public class GetPropertyTypesOperationResult extends GetObjectsOperationResult<IPropertyTypeId, PropertyType>
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @SuppressWarnings("unused")
+    private GetPropertyTypesOperationResult()
+    {
+    }
+
+    public GetPropertyTypesOperationResult(Map<IPropertyTypeId, PropertyType> objectMap)
+    {
+        super(objectMap);
+    }
+}
diff --git a/openbis_api/sourceTest/java/ch/ethz/sis/openbis/generic/sharedapi/v3/dictionary.txt b/openbis_api/sourceTest/java/ch/ethz/sis/openbis/generic/sharedapi/v3/dictionary.txt
index d7bbad7dd963576ae82f667f29a495ee955b8d3e..4b236e9ae5ce08a1a26dc762ce19fcfacd10a77f 100644
--- a/openbis_api/sourceTest/java/ch/ethz/sis/openbis/generic/sharedapi/v3/dictionary.txt
+++ b/openbis_api/sourceTest/java/ch/ethz/sis/openbis/generic/sharedapi/v3/dictionary.txt
@@ -1872,3 +1872,13 @@ Delete Vocabularies Operation
 Delete Vocabularies Operation Result
 Vocabulary Deletion Options
 
+create Property Types
+Create Property Types Operation
+Create Property Types Operation Result
+get Material Type Id
+Property Type Creation
+set Material Type Id
+
+get Property Types
+Get Property Types Operation
+Get Property Types Operation Result