From db7ea76c19359f9de102991556cc39ed5b6f4a90 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Mon, 26 Oct 2009 14:06:48 +0000
Subject: [PATCH] [LMS-1194] extended assignment registration (mainly server
 side)

SVN: 13067
---
 .../web/client/ICommonClientService.java      |   4 +-
 .../web/client/ICommonClientServiceAsync.java |   7 +-
 .../client/web/client/application/Dict.java   |   2 +
 .../PropertyTypeAssignmentForm.java           | 114 ++++++++++++++++--
 .../PropertyTypeAssignmentGrid.java           |  44 ++++++-
 .../ui/sample/SampleTypeSelectionWidget.java  |  18 +++
 .../web/server/CommonClientService.java       |   5 +-
 .../openbis/generic/server/CommonServer.java  |   5 +-
 .../generic/server/CommonServerLogger.java    |   6 +-
 .../business/bo/EntityTypePropertyTypeBO.java |  29 ++++-
 .../bo/IEntityTypePropertyTypeBO.java         |   2 +-
 .../dataaccess/IEntityPropertyTypeDAO.java    |   2 +
 .../dataaccess/db/EntityPropertyTypeDAO.java  |  32 ++++-
 .../openbis/generic/shared/ICommonServer.java |   2 +-
 .../cisd/openbis/public/common-dictionary.js  |   1 +
 .../generic/server/CommonServerTest.java      |   5 +-
 .../bo/EntityTypePropertyTypeBOTest.java      |  35 +++---
 .../server/dataaccess/db/AbstractDAOTest.java |   1 +
 .../shared/ICommonServer.java.expected        |   2 +-
 19 files changed, 261 insertions(+), 55 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index 3495a41fe5f..3edf8a61c27 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -429,8 +429,8 @@ public interface ICommonClientService extends IClientService
      * Assigns property type to entity type.
      */
     public String assignPropertyType(EntityKind entityKind, String propertyTypeCode,
-            String entityTypeCode, boolean isMandatory, String defaultValue)
-            throws UserFailureException;
+            String entityTypeCode, boolean isMandatory, String defaultValue, String section,
+            Long previousETPTOrdinal) throws UserFailureException;
 
     /**
      * Unassigns property type to entity type.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index 12ab982ed7e..92d9a1591d2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -357,11 +357,12 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listDataTypes(final AsyncCallback<List<DataType>> asyncCallback);
 
     /**
-     * @see ICommonClientService#assignPropertyType(EntityKind, String, String, boolean, String)
+     * @see ICommonClientService#assignPropertyType(EntityKind, String, String, boolean, String,
+     *      String, Long)
      */
     public void assignPropertyType(EntityKind entityKind, String propertyTypeCode,
-            String entityTypeCode, boolean isMandatory, String defaultValue,
-            AsyncCallback<String> process);
+            String entityTypeCode, boolean isMandatory, String defaultValue, String section,
+            Long previousETPTOrdinal, AsyncCallback<String> process);
 
     /**
      * @see ICommonClientService#updatePropertyTypeAssignment(EntityKind, String, String, String,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index d2e496231d9..723fccdffa3 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -318,6 +318,8 @@ public abstract class Dict
 
     public static final String MANDATORY = "mandatory";
 
+    public static final String SECTION_TOOLTIP = "section_tooltip";
+
     public static final String DEFAULT_VALUE = "default_value";
 
     public static final String DEFAULT_VALUE_TOOLTIP = "default_value_tooltip";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
index 17b35de4ea1..c63cc90b1cd 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentForm.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type;
 
+import java.util.List;
 import java.util.Set;
 
 import com.extjs.gxt.ui.client.Events;
@@ -47,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.Abstrac
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.data.DataSetTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment.ExperimentTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.PropertyFieldFactory;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.VarcharField;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.MaterialTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.sample.SampleTypeSelectionWidget;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.DropDownList;
@@ -54,6 +56,8 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.InfoBox;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 
 /**
@@ -90,6 +94,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
 
     protected static final String DEFAULT_VALUE_ID_PART = "default_value";
 
+    protected static final String SECTION_VALUE_ID_PART = "section_value";
+
     private final IViewContext<ICommonClientServiceAsync> viewContext;
 
     private SampleTypeSelectionWidget sampleTypeSelectionWidget;
@@ -106,6 +112,9 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
 
     private CheckBox mandatoryCheckbox;
 
+    // TODO 2009-10-26, Piotr Buczek: use combo box
+    private Field<String> sectionField;
+
     private Button saveButton;
 
     private final InfoBox infoBox;
@@ -168,6 +177,7 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                             public void handleEvent(BaseEvent be)
                             {
                                 updateDefaultField();
+                                updateEntityTypePropertyTypeFields();
                             }
                         });
         }
@@ -176,6 +186,7 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
 
     private DropDownList<?, ?> getTypeSelectionWidget()
     {
+        DropDownList<?, ?> result = null;
         switch (entityKind)
         {
             case EXPERIMENT:
@@ -188,7 +199,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                             new InfoBoxResetListener(infoBox));
                     FieldUtil.markAsMandatory(experimentTypeSelectionWidget);
                 }
-                return experimentTypeSelectionWidget;
+                result = experimentTypeSelectionWidget;
+                break;
             case SAMPLE:
                 if (sampleTypeSelectionWidget == null)
                 {
@@ -198,7 +210,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                             infoBox));
                     FieldUtil.markAsMandatory(sampleTypeSelectionWidget);
                 }
-                return sampleTypeSelectionWidget;
+                result = sampleTypeSelectionWidget;
+                break;
             case MATERIAL:
                 if (materialTypeSelectionWidget == null)
                 {
@@ -208,7 +221,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                             infoBox));
                     FieldUtil.markAsMandatory(materialTypeSelectionWidget);
                 }
-                return materialTypeSelectionWidget;
+                result = materialTypeSelectionWidget;
+                break;
             case DATA_SET:
                 if (dataSetTypeSelectionWidget == null)
                 {
@@ -218,9 +232,23 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
                             infoBox));
                     FieldUtil.markAsMandatory(dataSetTypeSelectionWidget);
                 }
-                return dataSetTypeSelectionWidget;
+                result = dataSetTypeSelectionWidget;
+                break;
+        }
+        if (result == null)
+        {
+            throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
+        } else
+        {
+            result.addListener(Events.SelectionChange, new Listener<BaseEvent>()
+                {
+                    public void handleEvent(BaseEvent be)
+                    {
+                        updateEntityTypePropertyTypeFields();
+                    }
+                });
+            return result;
         }
-        throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
     }
 
     private CheckBox getMandatoryCheckbox()
@@ -270,6 +298,15 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         return panel;
     }
 
+    private String getSectionValue()
+    {
+        if (sectionField != null)
+        {
+            return sectionField.getValue();
+        }
+        return null;
+    }
+
     private String getDefaultValue()
     {
         if (defaultValueField != null)
@@ -280,17 +317,33 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
     }
 
     private String getSelectedEntityCode()
+    {
+        return tryGetSelectedEntityType().getCode();
+    }
+
+    /**
+     * extracts ordinal of an entity type property type after which new property will be added
+     */
+    private Long getPreviousETPTOrdinal()
+    {
+        // development version - append
+        final List<? extends EntityTypePropertyType<?>> allETPTs =
+                tryGetSelectedEntityType().getAssignedPropertyTypes();
+        return (allETPTs.size() > 0) ? allETPTs.get(allETPTs.size() - 1).getOrdinal() : 0L;
+    }
+
+    private EntityType tryGetSelectedEntityType()
     {
         switch (entityKind)
         {
             case EXPERIMENT:
-                return experimentTypeSelectionWidget.tryGetSelectedExperimentType().getCode();
+                return experimentTypeSelectionWidget.tryGetSelectedExperimentType();
             case SAMPLE:
-                return sampleTypeSelectionWidget.tryGetSelectedSampleType().getCode();
+                return sampleTypeSelectionWidget.tryGetSelectedSampleType();
             case MATERIAL:
-                return materialTypeSelectionWidget.tryGetSelectedMaterialType().getCode();
+                return materialTypeSelectionWidget.tryGetSelectedMaterialType();
             case DATA_SET:
-                return dataSetTypeSelectionWidget.tryGetSelectedDataSetType().getCode();
+                return dataSetTypeSelectionWidget.tryGetSelectedDataSetType();
         }
         throw new IllegalArgumentException(UNSUPPORTED_ENTITY_KIND);
     }
@@ -303,6 +356,7 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         formPanel.add(typeSelectionWidget);
         formPanel.add(getMandatoryCheckbox());
         updateDefaultField();
+        updateEntityTypePropertyTypeFields();
 
         modificationManager.addObserver(propertyTypeWidget);
         modificationManager.addObserver(typeSelectionWidget);
@@ -374,6 +428,44 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
         }
     }
 
+    //
+
+    private void updateEntityTypePropertyTypeFields()
+    {
+        hideEntityTypePropertyTypeFields();
+        final PropertyType propertyType = propertyTypeSelectionWidget.tryGetSelectedPropertyType();
+        final EntityType entityType = tryGetSelectedEntityType();
+        if (propertyType != null && entityType != null)
+        {
+            System.err.println();
+            for (EntityTypePropertyType<?> etpt : entityType.getAssignedPropertyTypes())
+            {
+                System.err.println((propertyType.equals(etpt.getPropertyType()) ? "*" : "")
+                        + etpt.getPropertyType().getCode());
+            }
+            sectionField = new VarcharField(viewContext.getMessage(Dict.SECTION), false);
+            sectionField.setToolTip(viewContext.getMessage(Dict.SECTION_TOOLTIP));
+            sectionField.setId(createChildId(SECTION_VALUE_ID_PART
+                    + propertyType.isInternalNamespace() + propertyType.getSimpleCode()));
+
+            sectionField.show();
+            formPanel.add(sectionField);
+        }
+        layout();
+    }
+
+    private void hideEntityTypePropertyTypeFields()
+    {
+        if (sectionField != null)
+        {
+            sectionField.hide();
+            formPanel.remove(sectionField);
+            sectionField = null;
+        }
+    }
+
+    //
+
     private final void submitForm()
     {
         if (formPanel.isValid())
@@ -381,8 +473,8 @@ public final class PropertyTypeAssignmentForm extends LayoutContainer implements
             viewContext.getService().assignPropertyType(entityKind,
                     propertyTypeSelectionWidget.tryGetSelectedPropertyTypeCode(),
                     getSelectedEntityCode(), getMandatoryCheckbox().getValue(), getDefaultValue(),
-                    new AssignPropertyTypeCallback(viewContext));                     
-                    // TODO 2009-10-26, Piotr Buczek: add previousOrdinal
+                    getSectionValue(), getPreviousETPTOrdinal(),
+                    new AssignPropertyTypeCallback(viewContext));
         }
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
index 9f5cbe129e3..7fb4f898a21 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/property_type/PropertyTypeAssignmentGrid.java
@@ -16,7 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.extjs.gxt.ui.client.Events;
 import com.extjs.gxt.ui.client.Style.Scroll;
@@ -53,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
@@ -344,13 +348,47 @@ public class PropertyTypeAssignmentGrid extends
                     PropertyTypeAssignmentColDefKind.ENTITY_KIND });
     }
 
+    private Map<EntityType, List<EntityTypePropertyType<?>>> entityTypePropertyTypes;
+
+    private void extractETPTs(List<EntityTypePropertyType<?>> etpts)
+    {
+        entityTypePropertyTypes = new HashMap<EntityType, List<EntityTypePropertyType<?>>>();
+        for (EntityTypePropertyType<?> etpt : etpts)
+        {
+            List<EntityTypePropertyType<?>> list =
+                    entityTypePropertyTypes.get(etpt.getEntityType());
+            if (list == null)
+            {
+                list = new ArrayList<EntityTypePropertyType<?>>();
+                entityTypePropertyTypes.put(etpt.getEntityType(), list);
+            }
+            list.add(etpt);
+        }
+    }
+
     @Override
     protected void listEntities(
             DefaultResultSetConfig<String, EntityTypePropertyType<?>> resultSetConfig,
-            AbstractAsyncCallback<ResultSet<EntityTypePropertyType<?>>> callback)
+            final AbstractAsyncCallback<ResultSet<EntityTypePropertyType<?>>> callback)
     {
-        // TODO 2009-10-26, Piotr Buczek: extract information about assignments to specific entity type
-        viewContext.getService().listPropertyTypeAssignments(resultSetConfig, callback);
+        AbstractAsyncCallback<ResultSet<EntityTypePropertyType<?>>> extendedCallback =
+                new AbstractAsyncCallback<ResultSet<EntityTypePropertyType<?>>>(viewContext)
+                    {
+                        @Override
+                        protected void process(ResultSet<EntityTypePropertyType<?>> result)
+                        {
+                            extractETPTs(result.getList().extractOriginalObjects());
+                            callback.onSuccess(result);
+                        }
+
+                        @Override
+                        public void finishOnFailure(Throwable caught)
+                        {
+                            callback.finishOnFailure(caught);
+                        }
+
+                    };
+        viewContext.getService().listPropertyTypeAssignments(resultSetConfig, extendedCallback);
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
index 1eafe07a778..3775416eb4c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleTypeSelectionWidget.java
@@ -29,6 +29,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind.ObjectKind;
 
 /**
@@ -78,6 +79,23 @@ public final class SampleTypeSelectionWidget extends DropDownList<SampleTypeMode
         return super.tryGetSelected();
     }
 
+    /**
+     * Returns the {@link SampleType} currently selected.
+     * 
+     * @return <code>null</code> if nothing is selected yet.
+     */
+    public final List<SampleTypePropertyType> tryGetSelectedSamplePropertyTypes()
+    {
+        final SampleType selectedOrNull = tryGetSelectedSampleType();
+        if (selectedOrNull == null)
+        {
+            return null;
+        } else
+        {
+            return selectedOrNull.getAssignedPropertyTypes();
+        }
+    }
+
     @Override
     protected List<SampleTypeModel> convertItems(List<SampleType> result)
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index ef896d8c8e6..a2263d302c2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -974,14 +974,15 @@ public final class CommonClientService extends AbstractClientService implements
     }
 
     public String assignPropertyType(final EntityKind entityKind, final String propertyTypeCode,
-            final String entityTypeCode, final boolean isMandatory, final String defaultValue)
+            final String entityTypeCode, final boolean isMandatory, final String defaultValue,
+            final String section, final Long previousETPTOrdinal)
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
     {
         try
         {
             final String sessionToken = getSessionToken();
             return commonServer.assignPropertyType(sessionToken, entityKind, propertyTypeCode,
-                    entityTypeCode, isMandatory, defaultValue);
+                    entityTypeCode, isMandatory, defaultValue, section, previousETPTOrdinal);
         } catch (final UserFailureException e)
         {
             throw UserFailureExceptionTranslator.translate(e);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index b77e7fd0cb0..d1f48c39f50 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -630,7 +630,7 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
 
     public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
             final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue)
+            final String defaultValue, final String section, final Long previousETPTOrdinal)
     {
         assert sessionToken != null : "Unspecified session token";
         Session session = getSession(sessionToken);
@@ -639,7 +639,8 @@ public final class CommonServer extends AbstractServer<ICommonServer> implements
                 DtoConverters.convertEntityKind(entityKind);
         IEntityTypePropertyTypeBO etptBO =
                 businessObjectFactory.createEntityTypePropertyTypeBO(session, kind);
-        etptBO.createAssignment(propertyTypeCode, entityTypeCode, isMandatory, defaultValue);
+        etptBO.createAssignment(propertyTypeCode, entityTypeCode, isMandatory, defaultValue,
+                section, previousETPTOrdinal);
         return String.format("%s property type '%s' successfully assigned to %s type '%s'",
                 isMandatory ? "Mandatory" : "Optional", propertyTypeCode, kind.getLabel(),
                 entityTypeCode);
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index 2c59ce2296c..76200e65152 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -309,12 +309,12 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
 
     public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
             final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue)
+            final String defaultValue, final String section, final Long previousETPTOrdinal)
     {
         final String entityTypeFormat = entityKind.name() + "_TYPE(%S)";
         logTracking(sessionToken, "assign_property_type", " PROPERTY_TYPE(%S) " + entityTypeFormat
-                + " MANDATORY(%S) DEFAULT(%S)", propertyTypeCode, entityTypeCode, isMandatory,
-                defaultValue);
+                + " MANDATORY(%S) DEFAULT(%S) SECTION(%S) PREVIOUS_ORDINAL(%S)", propertyTypeCode,
+                entityTypeCode, isMandatory, defaultValue, section, previousETPTOrdinal);
         return null;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
index 017c4017da9..8d3677b3d5e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBO.java
@@ -91,11 +91,13 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
     }
 
     public void createAssignment(String propertyTypeCode, String entityTypeCode,
-            boolean isMandatory, String defaultValue)
+            boolean isMandatory, String defaultValue, String section, Long previousETPTOrdinal)
     {
-        EntityTypePE entityType = findEntityType(entityTypeCode); // TODO init property types
+        EntityTypePE entityType = findEntityType(entityTypeCode);
         PropertyTypePE propertyType = findPropertyType(propertyTypeCode);
-        assignment = createAssignment(isMandatory, entityType, propertyType);
+        assignment =
+                createAssignment(isMandatory, section, previousETPTOrdinal, entityType,
+                        propertyType);
         // fill default property values
         if (isMandatory)
         {
@@ -178,15 +180,23 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
     }
 
     private EntityTypePropertyTypePE createAssignment(final boolean mandatory,
-            final EntityTypePE entityType, final PropertyTypePE propertyType)
+            final String section, final Long previousETPTOrdinal, final EntityTypePE entityType,
+            final PropertyTypePE propertyType)
     {
         checkAssignmentDoesNotExist(entityType, propertyType);
+        // need to shift existing etpts to create space for new one
+        Long currentOrdinal = previousETPTOrdinal + 1;
+        increaseOrdinals(entityType, currentOrdinal, 1);
+
         final EntityTypePropertyTypePE etpt =
                 EntityTypePropertyTypePE.createEntityTypePropertyType(entityKind);
         etpt.setPropertyType(propertyType);
         etpt.setRegistrator(findRegistrator());
         etpt.setEntityType(entityType);
         etpt.setMandatory(mandatory);
+        etpt.setSection(section);
+        etpt.setOrdinal(currentOrdinal);
+
         try
         {
             getEntityPropertyTypeDAO(entityKind).createEntityPropertyTypeAssignment(etpt);
@@ -197,6 +207,17 @@ public class EntityTypePropertyTypeBO extends AbstractBusinessObject implements
         return etpt;
     }
 
+    /**
+     * shift specified entity type etpts by specified increment starting from etpt with specified
+     * ordinal
+     * 
+     * @param entityType
+     */
+    private void increaseOrdinals(EntityTypePE entityType, Long startOrdinal, int increment)
+    {
+        getEntityPropertyTypeDAO(entityKind).increaseOrdinals(entityType, startOrdinal, increment);
+    }
+
     private PropertyTypePE findPropertyType(String propertyTypeCode)
     {
         PropertyTypePE propertyType =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
index 9789403b776..ed204227d10 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IEntityTypePropertyTypeBO.java
@@ -30,7 +30,7 @@ public interface IEntityTypePropertyTypeBO
      * Create a new Entity Type - Property Type relation.
      */
     void createAssignment(String propertyTypeCode, String entityTypeCode, boolean isMandatory,
-            String defaultValue);
+            String defaultValue, String section, Long previousETPTOrdinal);
 
     /**
      * Loads assignments between specified property type and entity type.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
index 0680baf2d97..a24c1e9132e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IEntityPropertyTypeDAO.java
@@ -105,4 +105,6 @@ public interface IEntityPropertyTypeDAO
      */
     public void delete(EntityTypePropertyTypePE assignment);
 
+    public void increaseOrdinals(EntityTypePE entityType, Long startOrdinal, int increment);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
index 4943c14fd4d..dc77a8bafee 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/EntityPropertyTypeDAO.java
@@ -44,6 +44,7 @@ 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.dto.VocabularyTermWithStats;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 
 /**
  * The unique {@link IEntityPropertyTypeDAO} implementation.
@@ -118,11 +119,6 @@ final class EntityPropertyTypeDAO extends AbstractDAO implements IEntityProperty
         validatePE(entityPropertyTypeAssignement);
 
         final HibernateTemplate template = getHibernateTemplate();
-        // FIXME 2009-10-26, Piotr Buczek: remove when ordinal will be set in BO
-        if (entityPropertyTypeAssignement.getOrdinal() == null)
-        {
-            entityPropertyTypeAssignement.setOrdinal(1L);
-        }
         template.save(entityPropertyTypeAssignement);
         template.flush();
         if (operationLog.isInfoEnabled())
@@ -259,6 +255,32 @@ final class EntityPropertyTypeDAO extends AbstractDAO implements IEntityProperty
         }
     }
 
+    public void increaseOrdinals(EntityTypePE entityType, Long fromOrdinal, int increment)
+    {
+        // TODO 2009-10-26, Piotr Buczek: try to rewrite in HQL
+        Long entityTypeId = HibernateUtils.getId(entityType);
+        String entityTypeIdColumnName = "";
+        String entityTypePropertyTypeTableName = entityKind.name() + "_type_property_types";
+        switch (entityKind)
+        {
+            case DATA_SET:
+                entityTypeIdColumnName = "dsty_id";
+                break;
+            case EXPERIMENT:
+                entityTypeIdColumnName = "exty_id";
+                break;
+            case SAMPLE:
+                entityTypeIdColumnName = "saty_id";
+                break;
+            case MATERIAL:
+                entityTypeIdColumnName = "maty_id";
+                break;
+        }
+        executeUpdate("UPDATE " + entityTypePropertyTypeTableName + " SET ordinal = ordinal + ?"
+                + " WHERE " + entityTypeIdColumnName + " = ? AND ordinal >= ?", increment,
+                entityTypeId, fromOrdinal);
+    }
+
     public final void validateAndSaveUpdatedEntity(EntityTypePropertyTypePE entity)
     {
         assert entity != null : "entity is null";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 7a8b6813e78..7bf3871f80b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -386,7 +386,7 @@ public interface ICommonServer extends IServer
     @DatabaseCreateOrDeleteModification(value = ObjectKind.PROPERTY_TYPE_ASSIGNMENT)
     public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
             final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue);
+            final String defaultValue, final String section, final Long previousETPTOrdinal);
 
     /**
      * Update property type assignment to entity type.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index 64757fb23c3..0aff0662465 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -212,6 +212,7 @@ var common = {
   confirm_vocabulary_show_available_terms_in_chooosers_msg: "If this vocabulary has many terms (more than 100) application will slow down.<br><br>Are you sure?",
   vocabulary_show_available_terms_in_choosers: "Show available terms in choosers",
   missing_vocabulary_terms: "Missing vocabulary term.",
+  section_tooltip: "The name of the section in which the assigned property should appear in entity registration and edition forms.",
   default_value: "Initial Value",
   default_value_tooltip: "The value of the assigned property for all currently existing entities.",
   entity_type_assignments: "{0} Type Assignment{1}",
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
index 2170b387e81..937a3f6398b 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/CommonServerTest.java
@@ -1155,6 +1155,7 @@ public final class CommonServerTest extends AbstractServerTestCase
         final String entityTypeCode = "ARCHERY";
         final boolean mandatory = true;
         final String value = "50m";
+        final String section = "section 1";
         context.checking(new Expectations()
             {
                 {
@@ -1163,13 +1164,13 @@ public final class CommonServerTest extends AbstractServerTestCase
                     will(returnValue(entityTypePropertyTypeBO));
 
                     one(entityTypePropertyTypeBO).createAssignment(propertyTypeCode,
-                            entityTypeCode, mandatory, value);
+                            entityTypeCode, mandatory, value, section, 1L);
                 }
             });
         assertEquals(
                 "Mandatory property type 'USER.DISTANCE' successfully assigned to experiment type 'ARCHERY'",
                 createServer().assignPropertyType(SESSION_TOKEN, entityKind, propertyTypeCode,
-                        entityTypeCode, mandatory, value));
+                        entityTypeCode, mandatory, value, section, 1L));
         context.assertIsSatisfied();
     }
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
index ef1bd256ca7..911fe71e47e 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/EntityTypePropertyTypeBOTest.java
@@ -55,11 +55,11 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
                 {
                     one(entityPropertyTypeDAO).tryFindAssignment(experimentType, propertyType);
                     will(returnValue(etpt));
-                    
+
                     one(entityPropertyTypeDAO).delete(etpt);
                 }
             });
-        
+
         IEntityTypePropertyTypeBO bo = createEntityTypePropertyTypeBO(entityKind);
         bo.loadAssignment(propertyType.getCode(), experimentType.getCode());
         bo.deleteLoadedAssignment();
@@ -84,20 +84,20 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
         final ExperimentTypePropertyTypePE etpt = new ExperimentTypePropertyTypePE();
         prepareExperimentTypeAndPropertyType(entityKind, experimentType, propertyType);
         context.checking(new Expectations()
-        {
             {
-                one(entityPropertyTypeDAO).tryFindAssignment(experimentType, propertyType);
-                will(returnValue(etpt));
-            }
-        });
-        
+                {
+                    one(entityPropertyTypeDAO).tryFindAssignment(experimentType, propertyType);
+                    will(returnValue(etpt));
+                }
+            });
+
         IEntityTypePropertyTypeBO bo = createEntityTypePropertyTypeBO(entityKind);
         bo.loadAssignment(propertyType.getCode(), experimentType.getCode());
-        
+
         assertSame(etpt, bo.getLoadedAssignment());
         context.assertIsSatisfied();
     }
-    
+
     @Test
     public void testCreateAssignment()
     {
@@ -105,6 +105,7 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
         final EntityKind entityKind = EntityKind.EXPERIMENT;
         boolean mandatory = true;
         final String defaultValue = "50";
+        final String section = "section 1";
 
         final ExperimentPE experiment = new ExperimentPE();
         experiment.setCode("MAN");
@@ -114,11 +115,13 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
         final PropertyTypePE propertyType = createPropertyType();
         prepareExperimentTypeAndPropertyType(entityKind, experimentType, propertyType);
         context.checking(new Expectations()
-                    {
-                        {
+            {
+                {
                     one(entityPropertyTypeDAO).tryFindAssignment(experimentType, propertyType);
                     will(returnValue(null));
 
+                    one(entityPropertyTypeDAO).increaseOrdinals(experimentType, 2L, 1);
+
                     one(entityPropertyTypeDAO).createEntityPropertyTypeAssignment(
                             with(any(ExperimentTypePropertyTypePE.class)));
                     property.setEntityTypePropertyType(new ExperimentTypePropertyTypePE());
@@ -136,7 +139,8 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
                 }
             });
         final EntityTypePropertyTypeBO bo = createEntityTypePropertyTypeBO(EntityKind.EXPERIMENT);
-        bo.createAssignment(propertyType.getCode(), experimentType.getCode(), mandatory, defaultValue);
+        bo.createAssignment(propertyType.getCode(), experimentType.getCode(), mandatory,
+                defaultValue, section, 1L);
         assertTrue(experiment.getProperties().size() == 1);
         assertEquals(property, experiment.getProperties().toArray()[0]);
         assertEquals(experiment, property.getEntity());
@@ -164,8 +168,9 @@ public final class EntityTypePropertyTypeBOTest extends AbstractBOTest
 
                     allowing(daoFactory).getEntityPropertyTypeDAO(entityKind);
                     will(returnValue(entityPropertyTypeDAO));
-                    
-                }});
+
+                }
+            });
     }
 
     private ExperimentTypePE createExperimentType()
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractDAOTest.java
index 7a33f905a4b..6d120ec1e78 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractDAOTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/AbstractDAOTest.java
@@ -294,6 +294,7 @@ public abstract class AbstractDAOTest extends AbstractTransactionalTestNGSpringC
         result.setPropertyType(propertyType);
         result.setRegistrator(registrator);
         result.setRegistrationDate(new Date());
+        result.setOrdinal(1L);
         return result;
     }
 
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
index 7a8b6813e78..7bf3871f80b 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java.expected
@@ -386,7 +386,7 @@ public interface ICommonServer extends IServer
     @DatabaseCreateOrDeleteModification(value = ObjectKind.PROPERTY_TYPE_ASSIGNMENT)
     public String assignPropertyType(final String sessionToken, final EntityKind entityKind,
             final String propertyTypeCode, final String entityTypeCode, final boolean isMandatory,
-            final String defaultValue);
+            final String defaultValue, final String section, final Long previousETPTOrdinal);
 
     /**
      * Update property type assignment to entity type.
-- 
GitLab