From eb93b9db1d73571eb50f70e7266820e84e7f4eed Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Thu, 4 Oct 2012 08:38:59 +0000 Subject: [PATCH] SP-298, BIS-210: first functional GUI version SVN: 26986 --- .../OpenBIS-without-entry-point.gwt.xml | 1 + .../ManagedPropertyFormHelper.java | 156 +++++++++++++++++ .../ManagedPropertyGridActionDialog.java | 111 ++----------- .../openbis/generic/server/CommonServer.java | 28 ++-- .../dataaccess/EntityPropertiesConverter.java | 117 ++++++++++--- .../dto/ManagedInputWidgetDescription.java | 27 +++ .../api/IManagedInputWidgetDescription.java | 4 + .../ManagedPropertyEvaluator.java | 145 +++++++++++++--- .../application/ClientPluginFactory.java | 2 +- ...AbstractGenericEntityRegistrationForm.java | 19 ++- .../application/ClientPluginFactory.java | 3 +- .../dataset/DataSetPropertyEditor.java | 13 +- .../dataset/GenericDataSetEditForm.java | 10 +- ...ractGenericExperimentRegisterEditForm.java | 12 +- .../experiment/ExperimentPropertyEditor.java | 10 +- .../GenericExperimentRegistrationForm.java | 6 +- .../experiment/ManagedPropertyField.java | 157 ++++++++++++++++++ .../experiment/PropertiesEditor.java | 85 ++++++++-- .../material/GenericMaterialEditForm.java | 10 +- .../material/MaterialPropertyEditor.java | 10 +- ...AbstractGenericSampleRegisterEditForm.java | 21 ++- .../sample/GenericSampleEditForm.java | 2 +- .../sample/GenericSampleRegistrationForm.java | 5 +- .../sample/SamplePropertyEditor.java | 13 +- .../ManagedPropertyEvaluatorTest.java | 138 ++++++++++----- .../wizard/BiologicalSampleCreatingPage.java | 10 +- 26 files changed, 855 insertions(+), 260 deletions(-) create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyFormHelper.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ManagedPropertyField.java diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml b/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml index 6a418d5cdad..967a56e06cd 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml +++ b/openbis/source/java/ch/systemsx/cisd/openbis/OpenBIS-without-entry-point.gwt.xml @@ -11,6 +11,7 @@ --> <inherits name='com.google.gwt.user.User' /> <inherits name="com.google.gwt.i18n.I18N" /> + <inherits name="com.google.gwt.json.JSON" /> <!-- // Inherit the core EXT GWT stuff. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyFormHelper.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyFormHelper.java new file mode 100644 index 00000000000..6a3d5c72113 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyFormHelper.java @@ -0,0 +1,156 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.managed_property; + +import java.util.List; +import java.util.Map; + +import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction; +import com.extjs.gxt.ui.client.widget.form.FormPanel; +import com.extjs.gxt.ui.client.widget.form.SimpleComboBox; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.google.gwt.user.client.ui.AbstractImagePrototype; + +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil; +import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedComboBoxInputWidgetDescription; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; + +/** + * @author Franz-Josef Elmer + */ +public class ManagedPropertyFormHelper +{ + private final IViewContext<?> viewContext; + + private final FormPanel formPanel; + + private final Map<String, TextField<?>> inputFieldsByLabel; + + public ManagedPropertyFormHelper(IViewContext<?> viewContext, FormPanel formPanel, + Map<String, TextField<?>> inputFieldsByLabel) + { + this.viewContext = viewContext; + this.formPanel = formPanel; + this.inputFieldsByLabel = inputFieldsByLabel; + + } + + public void fillForm(List<IManagedInputWidgetDescription> inputWidgetDescriptions) + { + for (IManagedInputWidgetDescription inputDescription : inputWidgetDescriptions) + { + trySetBoundedValue(inputDescription); + TextField<?> field; + switch (inputDescription.getManagedInputFieldType()) + { + case TEXT: + field = createTextField(inputDescription); + break; + case MULTILINE_TEXT: + field = createMultilineTextField(inputDescription); + break; + case COMBO_BOX: + field = createComboBoxField(inputDescription); + break; + default: + throw new UnsupportedOperationException(); // can't happen + } + final String label = inputDescription.getLabel(); + if (label == null) + { + throwFailToCreateContentException("Label is not set in input widget description"); + } + field.setFieldLabel(label); + + if (inputDescription.getDescription() != null) + { + AbstractImagePrototype infoIcon = + AbstractImagePrototype.create(viewContext.getImageBundle().getInfoIcon()); + FieldUtil.addInfoIcon(field, inputDescription.getDescription(), + infoIcon.createImage()); + } + FieldUtil.setMandatoryFlag(field, inputDescription.isMandatory()); + + inputFieldsByLabel.put(label, field); + formPanel.add(field); + } + + } + + protected void trySetBoundedValue(IManagedInputWidgetDescription inputDescription) + { + } + + private TextField<?> createTextField(IManagedInputWidgetDescription inputDescription) + { + final TextField<String> field = new TextField<String>(); + if (inputDescription.getValue() != null) + { + FieldUtil.setValueWithUnescaping(field, inputDescription.getValue()); + field.updateOriginalValue(field.getValue()); + } + return field; + } + + private TextField<?> createMultilineTextField(IManagedInputWidgetDescription inputDescription) + { + final TextField<String> field = + new MultilineVarcharField(inputDescription.getLabel(), false); + if (inputDescription.getValue() != null) + { + FieldUtil.setValueWithUnescaping(field, inputDescription.getValue()); + field.updateOriginalValue(field.getValue()); + } + return field; + } + + private TextField<?> createComboBoxField(IManagedInputWidgetDescription inputDescription) + { + final SimpleComboBox<String> comboBox = new SimpleComboBox<String>(); + comboBox.setTriggerAction(TriggerAction.ALL); + comboBox.setEditable(false); + comboBox.setForceSelection(true); + if (inputDescription instanceof ManagedComboBoxInputWidgetDescription) + { + final ManagedComboBoxInputWidgetDescription comboBoxDescription = + (ManagedComboBoxInputWidgetDescription) inputDescription; + comboBox.add(comboBoxDescription.getOptions()); + + if (inputDescription.getValue() != null) + { + comboBox.setSimpleValue(inputDescription.getValue()); + comboBox.updateOriginalValue(comboBox.getValue()); + } + return comboBox; + } else + { + throwFailToCreateContentException("'" + inputDescription.getLabel() + + "' description should be a subclass of ManagedComboBoxInputWidgetDescription"); + return null; + } + } + + private void throwFailToCreateContentException(String detailedErrorMsg) + throws UserFailureException + { + throw new UserFailureException("Failed to create content.", detailedErrorMsg); + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyGridActionDialog.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyGridActionDialog.java index 8306ff66c42..76ab67e95fc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyGridActionDialog.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/managed_property/ManagedPropertyGridActionDialog.java @@ -23,25 +23,18 @@ import java.util.List; import java.util.Map; import com.extjs.gxt.ui.client.widget.Info; -import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction; -import com.extjs.gxt.ui.client.widget.form.SimpleComboBox; import com.extjs.gxt.ui.client.widget.form.SimpleComboValue; import com.extjs.gxt.ui.client.widget.form.TextField; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.AbstractImagePrototype; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.field.MultilineVarcharField; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.AbstractDataConfirmationDialog; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.FieldUtil; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.GWTUtils; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils; -import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ISerializableComparable; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedComboBoxInputWidgetDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedTableWidgetDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedUiTableActionDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ReportRowModel; @@ -70,6 +63,8 @@ public final class ManagedPropertyGridActionDialog extends private final Map<String, TextField<?>> inputFieldsByLabel = new LinkedHashMap<String, TextField<?>>(); + private final ManagedPropertyFormHelper formHelper; + public ManagedPropertyGridActionDialog(IViewContext<ICommonClientServiceAsync> viewContext, String editTitle, List<TableModelRowWithObject<ReportRowModel>> data, AsyncCallback<Void> callback, IEntityInformationHolder entity, @@ -82,6 +77,14 @@ public final class ManagedPropertyGridActionDialog extends this.callback = callback; this.managedAction = managedAction; setWidth(400); + formHelper = new ManagedPropertyFormHelper(viewContext, formPanel, inputFieldsByLabel) + { + @Override + protected void trySetBoundedValue(IManagedInputWidgetDescription inputDescription) + { + ManagedPropertyGridActionDialog.this.trySetBoundedValue(inputDescription); + } + }; } @Override @@ -130,44 +133,7 @@ public final class ManagedPropertyGridActionDialog extends formPanel.setLabelWidth(100); formPanel.setFieldWidth(200); - for (IManagedInputWidgetDescription inputDescription : managedAction - .getInputWidgetDescriptions()) - { - trySetBoundedValue(inputDescription); - TextField<?> field; - switch (inputDescription.getManagedInputFieldType()) - { - case TEXT: - field = createTextField(inputDescription); - break; - case MULTILINE_TEXT: - field = createMultilineTextField(inputDescription); - break; - case COMBO_BOX: - field = createComboBoxField(inputDescription); - break; - default: - throw new UnsupportedOperationException(); // can't happen - } - final String label = inputDescription.getLabel(); - if (label == null) - { - throwFailToCreateContentException("Label is not set in input widget description"); - } - field.setFieldLabel(label); - - if (inputDescription.getDescription() != null) - { - AbstractImagePrototype infoIcon = - AbstractImagePrototype.create(viewContext.getImageBundle().getInfoIcon()); - FieldUtil.addInfoIcon(field, inputDescription.getDescription(), - infoIcon.createImage()); - } - FieldUtil.setMandatoryFlag(field, inputDescription.isMandatory()); - - inputFieldsByLabel.put(label, field); - formPanel.add(field); - } + formHelper.fillForm(managedAction.getInputWidgetDescriptions()); } /** @@ -212,59 +178,4 @@ public final class ManagedPropertyGridActionDialog extends } } - private TextField<?> createTextField(IManagedInputWidgetDescription inputDescription) - { - final TextField<String> field = new TextField<String>(); - if (inputDescription.getValue() != null) - { - FieldUtil.setValueWithUnescaping(field, inputDescription.getValue()); - field.updateOriginalValue(field.getValue()); - } - return field; - } - - private TextField<?> createMultilineTextField(IManagedInputWidgetDescription inputDescription) - { - final TextField<String> field = - new MultilineVarcharField(inputDescription.getLabel(), false); - if (inputDescription.getValue() != null) - { - FieldUtil.setValueWithUnescaping(field, inputDescription.getValue()); - field.updateOriginalValue(field.getValue()); - } - return field; - } - - private TextField<?> createComboBoxField(IManagedInputWidgetDescription inputDescription) - { - final SimpleComboBox<String> comboBox = new SimpleComboBox<String>(); - comboBox.setTriggerAction(TriggerAction.ALL); - comboBox.setEditable(false); - comboBox.setForceSelection(true); - if (inputDescription instanceof ManagedComboBoxInputWidgetDescription) - { - final ManagedComboBoxInputWidgetDescription comboBoxDescription = - (ManagedComboBoxInputWidgetDescription) inputDescription; - comboBox.add(comboBoxDescription.getOptions()); - - if (inputDescription.getValue() != null) - { - comboBox.setSimpleValue(inputDescription.getValue()); - comboBox.updateOriginalValue(comboBox.getValue()); - } - return comboBox; - } else - { - throwFailToCreateContentException("'" + inputDescription.getLabel() - + "' description should be a subclass of ManagedComboBoxInputWidgetDescription"); - return null; - } - } - - private void throwFailToCreateContentException(String detailedErrorMsg) - throws UserFailureException - { - throw new UserFailureException("Failed to create content.", detailedErrorMsg); - } - } 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 c3fca1bbb41..dd132d94aab 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 @@ -198,7 +198,6 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListMaterialCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListSampleCriteria; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedTextInputWidgetDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedUiActionDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MatchingEntity; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; @@ -619,9 +618,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt List<? extends EntityTypePropertyType<?>> assignedPropertyTypes = entityType.getAssignedPropertyTypes(); - HashMap<String, List<IManagedInputWidgetDescription>> result = + return listManagedInputWidgetDescriptions(assignedPropertyTypes); + } + + private Map<String, List<IManagedInputWidgetDescription>> listManagedInputWidgetDescriptions( + List<? extends EntityTypePropertyType<?>> propertyTypes) + { + Map<String, List<IManagedInputWidgetDescription>> result = new HashMap<String, List<IManagedInputWidgetDescription>>(); - for (EntityTypePropertyType<?> entityTypePropertyType : assignedPropertyTypes) + for (EntityTypePropertyType<?> entityTypePropertyType : propertyTypes) { String propertyTypeCode = entityTypePropertyType.getPropertyType().getCode(); if (entityTypePropertyType.isManaged()) @@ -629,22 +634,13 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt String script = entityTypePropertyType.getScript().getScript(); ManagedPropertyEvaluator evaluator = ManagedPropertyEvaluatorFactory.createManagedPropertyEvaluator(script); - List<String> batchColumnNames = evaluator.getBatchColumnNames(); - if (batchColumnNames.isEmpty() == false) + List<IManagedInputWidgetDescription> inputWidgetDescriptions = + evaluator.getInputWidgetDescriptions(); + if (inputWidgetDescriptions.isEmpty() == false) { - List<IManagedInputWidgetDescription> descriptions = - new ArrayList<IManagedInputWidgetDescription>(); - for (String batchColumnName : batchColumnNames) - { - ManagedTextInputWidgetDescription description = - new ManagedTextInputWidgetDescription(); - description.setLabel(batchColumnName); - descriptions.add(description); - } - result.put(propertyTypeCode, descriptions); + result.put(propertyTypeCode, inputWidgetDescriptions); } } - } return result; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java index c79d113c023..a1cd6aa0d4f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/EntityPropertiesConverter.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -28,7 +29,10 @@ import java.util.Set; import org.hibernate.Session; +import com.fasterxml.jackson.databind.ObjectMapper; + import ch.rinn.restrictions.Private; +import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel; import ch.systemsx.cisd.common.collections.IKeyExtractor; import ch.systemsx.cisd.common.collections.TableMap; import ch.systemsx.cisd.common.collections.TableMap.UniqueKeyViolationStrategy; @@ -38,7 +42,9 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.util.KeyExtractorFacto import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedProperty; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; @@ -50,6 +56,8 @@ 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.VocabularyTermPE; import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; +import ch.systemsx.cisd.openbis.generic.shared.managed_property.ManagedPropertyEvaluator; +import ch.systemsx.cisd.openbis.generic.shared.managed_property.ManagedPropertyEvaluatorFactory; /** * The unique {@link IEntityPropertiesConverter} implementation. @@ -63,6 +71,15 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; */ public final class EntityPropertiesConverter implements IEntityPropertiesConverter { + private static final IKeyExtractor<PropertyTypePE, ExtendedEntityTypePropertyType> EXTENDED_ETPT_KEY_EXTRACTOR = + new IKeyExtractor<PropertyTypePE, ExtendedEntityTypePropertyType>() + { + @Override + public PropertyTypePE getKey(ExtendedEntityTypePropertyType etpt) + { + return etpt.getEntityTypePropertyTypePE().getPropertyType(); + } + }; private static final String NO_ENTITY_PROPERTY_VALUE_FOR_S = "Value of mandatory property '%s' not specified."; @@ -83,8 +100,8 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert new TableMap<String, PropertyTypePE>( KeyExtractorFactory.getPropertyTypeByCodeKeyExtractor()); - private Map<String /* Entity type code */, TableMap<PropertyTypePE, EntityTypePropertyTypePE>> entityTypePropertyTypesByEntityTypeAndPropertyType = - new HashMap<String, TableMap<PropertyTypePE, EntityTypePropertyTypePE>>(); + private Map<String /* Entity type code */, TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>> entityTypePropertyTypesByEntityTypeAndPropertyType = + new HashMap<String, TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>>(); private final ComplexPropertyValueHelper complexPropertyValueHelper; @@ -189,26 +206,24 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert return propertyType; } - private final EntityTypePropertyTypePE getEntityTypePropertyType( + private final ExtendedEntityTypePropertyType getEntityTypePropertyType( final EntityTypePE entityTypePE, final PropertyTypePE propertyType) { String entityTypeCode = entityTypePE.getCode(); - TableMap<PropertyTypePE, EntityTypePropertyTypePE> map = + TableMap<PropertyTypePE, ExtendedEntityTypePropertyType> map = entityTypePropertyTypesByEntityTypeAndPropertyType.get(entityTypeCode); if (map == null) { - IEntityPropertyTypeDAO entityPropertyTypeDAO = - daoFactory.getEntityPropertyTypeDAO(entityKind); - List<EntityTypePropertyTypePE> entityPropertyTypes = - entityPropertyTypeDAO.listEntityPropertyTypes(entityTypePE); + List<ExtendedEntityTypePropertyType> entityTypePropertyTypes = + getEntityTypePropertyTypes(entityTypePE); map = - new TableMap<PropertyTypePE, EntityTypePropertyTypePE>(entityPropertyTypes, - EntityTypePropertyTypeByPropertyTypeKeyExtractor.INSTANCE, + new TableMap<PropertyTypePE, ExtendedEntityTypePropertyType>( + entityTypePropertyTypes, EXTENDED_ETPT_KEY_EXTRACTOR, UniqueKeyViolationStrategy.KEEP_FIRST); entityTypePropertyTypesByEntityTypeAndPropertyType.put(entityTypeCode, map); } - final EntityTypePropertyTypePE entityTypePropertyType = map.tryGet(propertyType); + final ExtendedEntityTypePropertyType entityTypePropertyType = map.tryGet(propertyType); if (entityTypePropertyType == null) { @@ -219,14 +234,32 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert return entityTypePropertyType; } + private List<ExtendedEntityTypePropertyType> getEntityTypePropertyTypes( + EntityTypePE entityTypePE) + { + IEntityPropertyTypeDAO entityPropertyTypeDAO = + daoFactory.getEntityPropertyTypeDAO(entityKind); + List<EntityTypePropertyTypePE> entityPropertyTypes = + entityPropertyTypeDAO.listEntityPropertyTypes(entityTypePE); + List<ExtendedEntityTypePropertyType> result = + new ArrayList<ExtendedEntityTypePropertyType>(); + for (EntityTypePropertyTypePE entityTypePropertyTypePE : entityPropertyTypes) + { + result.add(new ExtendedEntityTypePropertyType(entityTypePropertyTypePE)); + } + return result; + } + private final <T extends EntityPropertyPE> T tryConvertProperty(final PersonPE registrator, final EntityTypePE entityTypePE, final IEntityProperty property) { final String propertyCode = property.getPropertyType().getCode(); final PropertyTypePE propertyType = getPropertyType(propertyCode); final String valueOrNull = property.tryGetAsString(); - final EntityTypePropertyTypePE entityTypePropertyTypePE = + ExtendedEntityTypePropertyType extendedETPT = getEntityTypePropertyType(entityTypePE, propertyType); + final EntityTypePropertyTypePE entityTypePropertyTypePE = + extendedETPT.getEntityTypePropertyTypePE(); if (entityTypePropertyTypePE.isMandatory() && valueOrNull == null) { throw UserFailureException.fromTemplate(NO_ENTITY_PROPERTY_VALUE_FOR_S, propertyCode); @@ -235,8 +268,9 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert { final String validated = propertyValueValidator.validatePropertyValue(propertyType, valueOrNull); + return createEntityProperty(registrator, propertyType, entityTypePropertyTypePE, - validated); + extendedETPT.translate(validated)); } return null; } @@ -517,27 +551,60 @@ public final class EntityPropertiesConverter implements IEntityPropertiesConvert // Helper classes // - private final static class EntityTypePropertyTypeByPropertyTypeKeyExtractor implements - IKeyExtractor<PropertyTypePE, EntityTypePropertyTypePE> + private static final class ExtendedEntityTypePropertyType { + private final EntityTypePropertyTypePE entityTypePropertyTypePE; + + private final List<IManagedInputWidgetDescription> inputWidgetDescriptions; - static final EntityTypePropertyTypeByPropertyTypeKeyExtractor INSTANCE = - new EntityTypePropertyTypeByPropertyTypeKeyExtractor(); + private ManagedPropertyEvaluator evaluator; - private EntityTypePropertyTypeByPropertyTypeKeyExtractor() + ExtendedEntityTypePropertyType(EntityTypePropertyTypePE entityTypePropertyTypePE) { - // Can not be instantiated. + this.entityTypePropertyTypePE = entityTypePropertyTypePE; + if (entityTypePropertyTypePE.isManaged()) + { + String script = entityTypePropertyTypePE.getScript().getScript(); + evaluator = ManagedPropertyEvaluatorFactory.createManagedPropertyEvaluator(script); + inputWidgetDescriptions = evaluator.getInputWidgetDescriptions(); + } else + { + inputWidgetDescriptions = Collections.emptyList(); + } } - // - // IKeyExtractor - // + public EntityTypePropertyTypePE getEntityTypePropertyTypePE() + { + return entityTypePropertyTypePE; + } - @Override - public final PropertyTypePE getKey(final EntityTypePropertyTypePE e) + @SuppressWarnings("unchecked") + String translate(String propertyValue) { - return e.getPropertyType(); + if (inputWidgetDescriptions.isEmpty() || propertyValue == null + || propertyValue.startsWith(BasicConstant.ERROR_PROPERTY_PREFIX)) + { + return propertyValue; + } + try + { + List<?> readValue = new ObjectMapper().readValue(propertyValue, List.class); + ManagedProperty managedProperty = new ManagedProperty(); + for (Object row : readValue) + { + if (row instanceof Map == false) + { + continue; + } + evaluator.updateFromBatchInput(managedProperty, (Map<String, String>) row); + } + return managedProperty.getValue(); + } catch (Exception ex) + { + throw CheckedExceptionTunnel.wrapIfNecessary(ex); + } } + } public interface IHibernateSessionProvider diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedInputWidgetDescription.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedInputWidgetDescription.java index bb4e5c96fef..9eb0400a2c5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedInputWidgetDescription.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedInputWidgetDescription.java @@ -16,6 +16,8 @@ package ch.systemsx.cisd.openbis.generic.shared.basic.dto; +import org.apache.commons.lang.StringUtils; + import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; /** @@ -25,6 +27,8 @@ public abstract class ManagedInputWidgetDescription implements IManagedInputWidg { private static final long serialVersionUID = 1L; + private String code; + private String label; private String value; @@ -37,6 +41,21 @@ public abstract class ManagedInputWidgetDescription implements IManagedInputWidg // IManagedInputWidgetDescription // + @Override + public String getCode() + { + return code; + } + + public void setCode(String code) + { + if (StringUtils.isBlank(code)) + { + throw new IllegalArgumentException("Code is null or a blank string."); + } + this.code = code.toUpperCase(); + } + @Override public String getLabel() { @@ -45,7 +64,15 @@ public abstract class ManagedInputWidgetDescription implements IManagedInputWidg public void setLabel(String label) { + if (StringUtils.isBlank(label)) + { + throw new IllegalArgumentException("Label is null or a blank string."); + } this.label = label; + if (code == null) + { + code = label.toUpperCase(); + } } @Override diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/api/IManagedInputWidgetDescription.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/api/IManagedInputWidgetDescription.java index d9cda035907..cd35ca1a00e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/api/IManagedInputWidgetDescription.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/api/IManagedInputWidgetDescription.java @@ -26,6 +26,10 @@ import java.io.Serializable; // NOTE: All methods of this interface are part of the Managed Properties API. public interface IManagedInputWidgetDescription extends Serializable { + /** + * Returns the code of this input field. + */ + String getCode(); /** * @return label of this input field diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluator.java index a4dd0c5ebb8..18ccfba256b 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluator.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluator.java @@ -17,9 +17,10 @@ package ch.systemsx.cisd.openbis.generic.shared.managed_property; import java.util.ArrayList; -import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.log4j.Logger; @@ -27,6 +28,8 @@ import ch.systemsx.cisd.common.evaluator.Evaluator; import ch.systemsx.cisd.common.evaluator.EvaluatorException; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ManagedUiActionDescriptionFactory; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedUiAction; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE; @@ -38,6 +41,30 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE; */ public class ManagedPropertyEvaluator { + private static final class UniqunessChecker + { + private final Set<String> codes = new HashSet<String>(); + + private final String type; + + private final String codeName; + + UniqunessChecker(String type, String codeName) + { + this.type = type; + this.codeName = codeName; + } + + void check(String code) + { + if (codes.add(code) == false) + { + throw new EvaluatorException("There is already " + type + " with " + codeName + + ": " + code); + } + } + } + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, ManagedPropertyEvaluator.class); @@ -56,6 +83,11 @@ public class ManagedPropertyEvaluator */ private static final String BATCH_COLUMN_NAMES_FUNCTION = "batchColumnNames"; + /** + * The name of the function that returns an array of @IManagedInputWidgetDescription. + */ + private static final String INPUT_WIDGETS_FUNCTION = "inputWidgets"; + /** * The name of the function that expects a map of bindings. */ @@ -71,45 +103,101 @@ public class ManagedPropertyEvaluator private final boolean updateFromBatchFunctionDefined; + private List<IManagedInputWidgetDescription> inputWidgetDescriptions; + public ManagedPropertyEvaluator(String scriptExpression) { evaluator = new Evaluator("", ManagedPropertyFunctions.class, scriptExpression); updateFromBatchFunctionDefined = evaluator.hasFunction(UPDATE_FROM_BATCH_INPUT_FUNCTION); - List<String> names = new ArrayList<String>(); - if (evaluator.hasFunction(BATCH_COLUMN_NAMES_FUNCTION)) + boolean batchColumnNamesFunctionDefined = + evaluator.hasFunction(BATCH_COLUMN_NAMES_FUNCTION); + boolean inputWidgetsFunctionDefined = evaluator.hasFunction(INPUT_WIDGETS_FUNCTION); + checkCombinationsOfDefinedFunctions(batchColumnNamesFunctionDefined, + inputWidgetsFunctionDefined); + columnNames = new ArrayList<String>(); + inputWidgetDescriptions = new ArrayList<IManagedInputWidgetDescription>(); + if (inputWidgetsFunctionDefined) { - if (updateFromBatchFunctionDefined == false) - { - throw new EvaluatorException("Function '" + BATCH_COLUMN_NAMES_FUNCTION - + "' defined but not '" + UPDATE_FROM_BATCH_INPUT_FUNCTION + "'."); - } - Object result = evaluator.evalFunction(BATCH_COLUMN_NAMES_FUNCTION); - if (result instanceof List == false) + List<?> widgets = evalFunction(INPUT_WIDGETS_FUNCTION); + UniqunessChecker uniqunessChecker = new UniqunessChecker("an input widget", "code"); + for (int i = 0; i < widgets.size(); i++) { - throw new EvaluatorException("Function '" + BATCH_COLUMN_NAMES_FUNCTION - + "' doesn't return a List but an object of type '" - + result.getClass().getName() + "': " + result); + Object widget = widgets.get(i); + if (widget == null) + { + throw new EvaluatorException("Function " + INPUT_WIDGETS_FUNCTION + + " has returned a list where the " + (i + 1) + ". element is null."); + } + if (widget instanceof IManagedInputWidgetDescription == false) + { + throw new EvaluatorException("Function " + INPUT_WIDGETS_FUNCTION + + " has returned a list where the " + (i + 1) + + ". element isn't of type " + + IManagedInputWidgetDescription.class.getName() + " but " + + widget.getClass().getName() + "."); + } + IManagedInputWidgetDescription widgetDescription = + (IManagedInputWidgetDescription) widget; + inputWidgetDescriptions.add(widgetDescription); + if (batchColumnNamesFunctionDefined == false) + { + String code = widgetDescription.getCode(); + uniqunessChecker.check(code); + columnNames.add(code); + } } - List<?> list = (List<?>) result; - List<String> notUpperCaseNames = new ArrayList<String>(); + } + if (batchColumnNamesFunctionDefined) + { + List<?> list = evalFunction(BATCH_COLUMN_NAMES_FUNCTION); + UniqunessChecker uniqunessChecker = + new UniqunessChecker("a batch column", "name in uppercase"); + ManagedUiActionDescriptionFactory descriptionFactory = + new ManagedUiActionDescriptionFactory(); for (Object element : list) { String columnName = element.toString(); - if (columnName.toUpperCase().equals(columnName) == false) + String code = columnName.toUpperCase(); + uniqunessChecker.check(code); + columnNames.add(code); + if (inputWidgetsFunctionDefined == false) { - notUpperCaseNames.add(columnName); + inputWidgetDescriptions + .add(descriptionFactory.createTextInputField(columnName)); } - names.add(columnName); - } - if (notUpperCaseNames.isEmpty() == false) - { - throw new EvaluatorException( - "The following batch column names as returned by function '" - + BATCH_COLUMN_NAMES_FUNCTION + "' are not in upper case: " - + notUpperCaseNames); } } - columnNames = Collections.unmodifiableList(names); + } + + private void checkCombinationsOfDefinedFunctions(boolean batchColumnNamesFunctionDefined, + boolean inputWidgetsFunctionDefined) + { + if ((batchColumnNamesFunctionDefined || inputWidgetsFunctionDefined) + && updateFromBatchFunctionDefined == false) + { + StringBuilder builder = new StringBuilder("Function "); + builder.append(UPDATE_FROM_BATCH_INPUT_FUNCTION); + builder.append(" is not defined although function"); + boolean both = batchColumnNamesFunctionDefined && inputWidgetsFunctionDefined; + builder.append(both ? "s " : " "); + builder.append(batchColumnNamesFunctionDefined ? BATCH_COLUMN_NAMES_FUNCTION : ""); + builder.append(both ? " and " : ""); + builder.append(inputWidgetsFunctionDefined ? INPUT_WIDGETS_FUNCTION : ""); + builder.append(both ? " are defined." : " is defined."); + throw new EvaluatorException(builder.toString()); + } + } + + private List<?> evalFunction(String functionName) + { + Object result = evaluator.evalFunction(functionName); + if (result instanceof List == false) + { + throw new EvaluatorException("Function '" + functionName + + "' doesn't return a List but an object of type '" + + result.getClass().getName() + "': " + result); + } + return (List<?>) result; } public void configureUI(IManagedProperty managedProperty, EntityPropertyPE entityPropertyPE) @@ -142,6 +230,11 @@ public class ManagedPropertyEvaluator return columnNames; } + public List<IManagedInputWidgetDescription> getInputWidgetDescriptions() + { + return inputWidgetDescriptions; + } + public void updateFromBatchInput(IManagedProperty managedProperty, Map<String, String> bindings) { if (updateFromBatchFunctionDefined == false) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/demo/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/demo/client/web/client/application/ClientPluginFactory.java index e871e661930..07faf80dca8 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/demo/client/web/client/application/ClientPluginFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/demo/client/web/client/application/ClientPluginFactory.java @@ -170,7 +170,7 @@ public final class ClientPluginFactory extends AbstractClientPluginFactory<DemoV { GenericSampleRegistrationForm form = new GenericSampleRegistrationForm(new GenericViewContext(getViewContext() - .getCommonViewContext()), sampleType, context); + .getCommonViewContext()), inputWidgetDescriptions, sampleType, context); return new DatabaseModificationAwareWidget(form, form); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java index ef039d3a4d5..4f9fea55b83 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/AbstractGenericEntityRegistrationForm.java @@ -17,7 +17,9 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import com.extjs.gxt.ui.client.widget.form.Field; @@ -40,6 +42,7 @@ 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.IEntityProperty; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; @@ -68,6 +71,8 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType protected PropertiesEditor<T, S> propertiesEditor; + private final Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions; + // --------------------------------------------------------------------------------------------- // Constructors // --------------------------------------------------------------------------------------------- @@ -76,11 +81,16 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType */ protected AbstractGenericEntityRegistrationForm( final IViewContext<IGenericClientServiceAsync> viewContext, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptionsOrNull, IIdAndCodeHolder identifiableOrNull, EntityKind entityKind) { super(viewContext, createId(identifiableOrNull, entityKind), DEFAULT_LABEL_WIDTH + 20, DEFAULT_FIELD_WIDTH); this.viewContext = viewContext; + this.inputWidgetDescriptions = + inputWidgetDescriptionsOrNull == null ? Collections + .<String, List<IManagedInputWidgetDescription>> emptyMap() + : inputWidgetDescriptionsOrNull; this.entityKind = entityKind; this.techIdOrNull = TechId.create(identifiableOrNull); } @@ -89,9 +99,11 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType * For registering new entity. */ protected AbstractGenericEntityRegistrationForm( - final IViewContext<IGenericClientServiceAsync> viewContext, EntityKind entityKind) + final IViewContext<IGenericClientServiceAsync> viewContext, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + EntityKind entityKind) { - this(viewContext, null, entityKind); + this(viewContext, inputWidgetDescriptions, null, entityKind); } // --------------------------------------------------------------------------------------------- @@ -176,7 +188,7 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType private final void createCommonFormFields() { propertiesEditor = - createPropertiesEditor(createId(techIdOrNull, entityKind), + createPropertiesEditor(createId(techIdOrNull, entityKind), inputWidgetDescriptions, viewContext.getCommonViewContext()); codeField = new CodeFieldWithGenerator(viewContext, viewContext.getMessage(Dict.CODE), @@ -311,6 +323,7 @@ public abstract class AbstractGenericEntityRegistrationForm<T extends EntityType * Returns the {@link PropertiesEditor} to be used for . */ abstract protected PropertiesEditor<T, S> createPropertiesEditor(String string, + Map<String, List<IManagedInputWidgetDescription>> widgetDescriptions, IViewContext<ICommonClientServiceAsync> context); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java index 90dd9fb1962..f57899f329c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/ClientPluginFactory.java @@ -223,7 +223,8 @@ public final class ClientPluginFactory extends AbstractClientPluginFactory<Gener final ActionContext context) { GenericSampleRegistrationForm form = - new GenericSampleRegistrationForm(getViewContext(), sampleType, context); + new GenericSampleRegistrationForm(getViewContext(), inputWidgetDescriptions, + sampleType, context); return new DatabaseModificationAwareWidget(form, form); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertyEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertyEditor.java index cd034a775df..93c4039cdca 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertyEditor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/DataSetPropertyEditor.java @@ -16,19 +16,24 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.dataset; +import java.util.List; +import java.util.Map; + import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; -public class DataSetPropertyEditor extends - PropertiesEditor<DataSetType, DataSetTypePropertyType> +public class DataSetPropertyEditor extends PropertiesEditor<DataSetType, DataSetTypePropertyType> { - public DataSetPropertyEditor(String id, IViewContext<ICommonClientServiceAsync> viewContext) + public DataSetPropertyEditor(String id, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> viewContext) { - super(id, viewContext); + super(id, inputWidgetDescriptions, viewContext); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java index de50cac187a..6f2401bce4e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/dataset/GenericDataSetEditForm.java @@ -20,6 +20,7 @@ import static ch.systemsx.cisd.openbis.generic.client.web.client.application.fra import java.util.ArrayList; import java.util.List; +import java.util.Map; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.Events; @@ -63,6 +64,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkDataSet; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.AbstractGenericEntityRegistrationForm; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; @@ -108,7 +110,7 @@ public final class GenericDataSetEditForm extends private GenericDataSetEditForm(IViewContext<IGenericClientServiceAsync> viewContext, IIdAndCodeHolder identifiable) { - super(viewContext, identifiable, EntityKind.DATA_SET); + super(viewContext, null, identifiable, EntityKind.DATA_SET); setRevertButtonVisible(true); simpleId = createSimpleId(identifiable, EntityKind.DATA_SET); } @@ -202,9 +204,11 @@ public final class GenericDataSetEditForm extends @Override protected PropertiesEditor<DataSetType, DataSetTypePropertyType> createPropertiesEditor( - String id, IViewContext<ICommonClientServiceAsync> context) + String id, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> context) { - DataSetPropertyEditor editor = new DataSetPropertyEditor(id, context); + DataSetPropertyEditor editor = + new DataSetPropertyEditor(id, inputWidgetDescriptions, context); return editor; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java index 74c5c44343f..7ac62518950 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/AbstractGenericExperimentRegisterEditForm.java @@ -99,8 +99,6 @@ abstract public class AbstractGenericExperimentRegisterEditForm extends private LabelField templateField; - private final Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions; - protected AbstractGenericExperimentRegisterEditForm( IViewContext<IGenericClientServiceAsync> viewContext, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, @@ -114,9 +112,7 @@ abstract public class AbstractGenericExperimentRegisterEditForm extends Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, ActionContext actionContext, IIdAndCodeHolder identifiable) { - super(viewContext, identifiable, EntityKind.EXPERIMENT); - - this.inputWidgetDescriptions = inputWidgetDescriptions; + super(viewContext, inputWidgetDescriptions, identifiable, EntityKind.EXPERIMENT); simpleId = createSimpleId(identifiable, EntityKind.EXPERIMENT); attachmentsSessionKey = simpleId + "_attachments"; samplesSessionKey = simpleId + "_samples"; @@ -179,9 +175,11 @@ abstract public class AbstractGenericExperimentRegisterEditForm extends @Override protected PropertiesEditor<ExperimentType, ExperimentTypePropertyType> createPropertiesEditor( - String id, IViewContext<ICommonClientServiceAsync> context) + String id, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> context) { - ExperimentPropertyEditor editor = new ExperimentPropertyEditor(id, context); + ExperimentPropertyEditor editor = + new ExperimentPropertyEditor(id, inputWidgetDescriptions, context); return editor; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentPropertyEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentPropertyEditor.java index b700732138b..082a0419578 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentPropertyEditor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ExperimentPropertyEditor.java @@ -16,18 +16,24 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment; +import java.util.List; +import java.util.Map; + import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExperimentTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; public class ExperimentPropertyEditor extends PropertiesEditor<ExperimentType, ExperimentTypePropertyType> { - public ExperimentPropertyEditor(String id, IViewContext<ICommonClientServiceAsync> viewContext) + public ExperimentPropertyEditor(String id, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> viewContext) { - super(id, viewContext); + super(id, inputWidgetDescriptions, viewContext); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java index bd76942dff7..dce9786ba70 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/GenericExperimentRegistrationForm.java @@ -110,9 +110,11 @@ public final class GenericExperimentRegistrationForm extends @Override protected PropertiesEditor<ExperimentType, ExperimentTypePropertyType> createPropertiesEditor( - String id, IViewContext<ICommonClientServiceAsync> context) + String id, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> context) { - ExperimentPropertyEditor editor = new ExperimentPropertyEditor(id, context); + ExperimentPropertyEditor editor = + new ExperimentPropertyEditor(id, inputWidgetDescriptions, context); return editor; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ManagedPropertyField.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ManagedPropertyField.java new file mode 100644 index 00000000000..2e15b428598 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/ManagedPropertyField.java @@ -0,0 +1,157 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.Listener; +import com.extjs.gxt.ui.client.event.MessageBoxEvent; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.Dialog; +import com.extjs.gxt.ui.client.widget.HorizontalPanel; +import com.extjs.gxt.ui.client.widget.MessageBox; +import com.extjs.gxt.ui.client.widget.VerticalPanel; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.form.Field; +import com.extjs.gxt.ui.client.widget.form.FormPanel; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.google.gwt.user.client.ui.Widget; + +import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.AbstractRegistrationForm; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.managed_property.ManagedPropertyFormHelper; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; + +/** + * @author Franz-Josef Elmer + */ +public class ManagedPropertyField extends Field<List<Map<String, String>>> +{ + private static final int SPACING = 3; + + private static final class Section + { + private final Map<String, TextField<?>> inputFields; + + Section(Map<String, TextField<?>> inputFields) + { + this.inputFields = inputFields; + } + } + + private final IViewContext<?> viewContext; + + private final List<IManagedInputWidgetDescription> widgetDescriptions; + + private final VerticalPanel verticalPanel; + + private List<Section> sections = new ArrayList<Section>(); + + public ManagedPropertyField(IViewContext<?> viewContext, String label, boolean isMandatory, + List<IManagedInputWidgetDescription> widgetDescriptions) + { + this.viewContext = viewContext; + this.widgetDescriptions = widgetDescriptions; + verticalPanel = new VerticalPanel(); + verticalPanel.setHorizontalAlign(HorizontalAlignment.RIGHT); + + Button addButton = new Button("Add More"); + addButton.addSelectionListener(new SelectionListener<ButtonEvent>() + { + @Override + public void componentSelected(ButtonEvent ce) + { + addNewSection(); + } + }); + addButton.setToolTip("Add a new section."); + verticalPanel.add(addButton); + addNewSection(); + } + + public Widget getWidget() + { + return verticalPanel; + } + + @Override + public List<Map<String, String>> getValue() + { + List<Map<String, String>> list = new ArrayList<Map<String, String>>(); + for (Section section : sections) + { + HashMap<String, String> row = new HashMap<String, String>(); + for (Entry<String, TextField<?>> entry : section.inputFields.entrySet()) + { + row.put(entry.getKey(), entry.getValue().getRawValue()); + } + list.add(row); + } + return list; + } + + private void addNewSection() + { + FormPanel formPanel = new FormPanel(); + formPanel.setLabelWidth(AbstractRegistrationForm.DEFAULT_LABEL_WIDTH - SPACING - 2); + formPanel.setFieldWidth(AbstractRegistrationForm.DEFAULT_FIELD_WIDTH); + formPanel.setHeaderVisible(false); + Map<String, TextField<?>> inputFieldsByLabel = new HashMap<String, TextField<?>>(); + ManagedPropertyFormHelper formHelper = + new ManagedPropertyFormHelper(viewContext, formPanel, inputFieldsByLabel); + formHelper.fillForm(widgetDescriptions); + final HorizontalPanel horizontalPanel = new HorizontalPanel(); + horizontalPanel.setSpacing(SPACING); + horizontalPanel.add(formPanel); + Button removeButton = new Button("-"); + removeButton.setToolTip("Delete this section."); + final Section section = new Section(inputFieldsByLabel); + removeButton.addSelectionListener(new SelectionListener<ButtonEvent>() + { + @Override + public void componentSelected(ButtonEvent ce) + { + MessageBox.confirm("Delete Section", + "Do you really want to delete this section?", + new Listener<MessageBoxEvent>() + { + @Override + public void handleEvent(MessageBoxEvent be) + { + Button buttonClicked = be.getButtonClicked(); + if (Dialog.YES.equals(buttonClicked.getItemId())) + { + sections.remove(section); + verticalPanel.remove(horizontalPanel); + verticalPanel.layout(); + } + } + }); + } + }); + horizontalPanel.add(removeButton); + sections.add(section); + verticalPanel.insert(horizontalPanel, verticalPanel.getItemCount() - 1); + verticalPanel.layout(); + } +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java index 5ccaf55064f..e96b6ec02af 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/experiment/PropertiesEditor.java @@ -20,10 +20,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import com.extjs.gxt.ui.client.widget.form.FieldSet; import com.extjs.gxt.ui.client.widget.form.FormPanel; import com.extjs.gxt.ui.client.widget.layout.FormLayout; +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONString; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; @@ -39,6 +43,7 @@ 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.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; /** * @author Izabela Adamczyk @@ -54,6 +59,8 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp private final IViewContext<ICommonClientServiceAsync> viewContext; + private final Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions; + protected IEntityProperty createEntityProperty() { return new EntityProperty(); @@ -62,9 +69,12 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp /** * Requires initial values of properties. */ - protected PropertiesEditor(String id, IViewContext<ICommonClientServiceAsync> viewContext) + protected PropertiesEditor(String id, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> viewContext) { this.id = id; + this.inputWidgetDescriptions = inputWidgetDescriptions; this.viewContext = viewContext; } @@ -129,13 +139,20 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp assert viewContext != null; final DatabaseModificationAwareField<?> field; final boolean isMandatory = etpt.isMandatory(); - final String label = - PropertyTypeRenderer.getDisplayName(etpt.getPropertyType(), propertyTypes); - final String propertyTypeCode = etpt.getPropertyType().getCode(); - boolean isManaged = etpt.isManaged(); - field = - PropertyFieldFactory.createField(etpt.getPropertyType(), isMandatory, label, - createFormFieldId(getId(), propertyTypeCode), value, viewContext); + PropertyType propertyType = etpt.getPropertyType(); + final String label = PropertyTypeRenderer.getDisplayName(propertyType, propertyTypes); + final String propertyTypeCode = propertyType.getCode(); + List<IManagedInputWidgetDescription> widgetDescriptions = + inputWidgetDescriptions.get(propertyTypeCode); + if (widgetDescriptions != null && widgetDescriptions.isEmpty() == false) + { + field = createManagedPropertySection(label, isMandatory, widgetDescriptions); + } else + { + field = + PropertyFieldFactory.createField(propertyType, isMandatory, label, + createFormFieldId(getId(), propertyTypeCode), value, viewContext); + } field.get().setData(ETPT, etpt); GWTUtils.setToolTip(field.get(), propertyTypeCode); // Hide any properties that are not to be shown in edit/update views (unless in debugging @@ -147,6 +164,13 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp return field; } + private DatabaseModificationAwareField<?> createManagedPropertySection(String label, + boolean isMandatory, List<IManagedInputWidgetDescription> widgetDescriptions) + { + return DatabaseModificationAwareField.wrapUnaware(new ManagedPropertyField(viewContext, + label, isMandatory, widgetDescriptions)); + } + private boolean isDebuggingModeEnabled() { return viewContext.getDisplaySettingsManager().isDebuggingModeEnabled(); @@ -177,8 +201,27 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp if (etpt != null) { final IEntityProperty entityProperty = createEntityProperty(); - entityProperty.setValue(PropertyFieldFactory.valueToString(value)); - entityProperty.setPropertyType(etpt.getPropertyType()); + PropertyType propertyType = etpt.getPropertyType(); + String valueAsString = PropertyFieldFactory.valueToString(value); + if (inputWidgetDescriptions.get(propertyType.getCode()) != null) + { + JSONArray jsonArray = new JSONArray(); + @SuppressWarnings("unchecked") + List<Map<String, String>> rows = (List<Map<String, String>>) value; + for (int i = 0; i < rows.size(); i++) + { + Map<String, String> row = rows.get(i); + JSONObject jsonObject = new JSONObject(); + for (Entry<String, String> entry : row.entrySet()) + { + jsonObject.put(entry.getKey(), new JSONString(entry.getValue())); + } + jsonArray.set(i, jsonObject); + } + valueAsString = jsonArray.toString(); + } + entityProperty.setValue(valueAsString); + entityProperty.setPropertyType(propertyType); properties.add(entityProperty); } } @@ -227,7 +270,21 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp currentSectionFieldSet.add(field.get()); } else { - form.add(field.get()); + if (field.get() instanceof ManagedPropertyField) + { + PropertyType propertyType = etpt.getPropertyType(); + String label = propertyType.getLabel(); + if (etpt.isMandatory()) + { + label += " *"; + } + FieldSet fieldSet = createSectionFieldSet(label); + fieldSet.add(((ManagedPropertyField) field.get()).getWidget()); + form.add(fieldSet); + } else + { + form.add(field.get()); + } } previousSection = currentSection; @@ -241,13 +298,13 @@ abstract public class PropertiesEditor<T extends EntityType, S extends EntityTyp private FieldSet createSectionFieldSet(String sectionName) { - return new PropertiesSectionFileSet(sectionName); + return new PropertiesSectionFieldSet(sectionName); } - private static final class PropertiesSectionFileSet extends FieldSet + private static final class PropertiesSectionFieldSet extends FieldSet { - public PropertiesSectionFileSet(final String sectionName) + public PropertiesSectionFieldSet(final String sectionName) { createForm(sectionName); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java index 22e62919ebd..5f08018d6fc 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/GenericMaterialEditForm.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.ma import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback; @@ -31,6 +32,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.AbstractGenericEntityRegistrationForm; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; @@ -57,7 +59,7 @@ public final class GenericMaterialEditForm extends private GenericMaterialEditForm(IViewContext<IGenericClientServiceAsync> viewContext, IIdAndCodeHolder identifiable, boolean editMode) { - super(viewContext, identifiable, EntityKind.MATERIAL); + super(viewContext, null, identifiable, EntityKind.MATERIAL); setRevertButtonVisible(true); } @@ -100,9 +102,11 @@ public final class GenericMaterialEditForm extends @Override protected PropertiesEditor<MaterialType, MaterialTypePropertyType> createPropertiesEditor( - String id, IViewContext<ICommonClientServiceAsync> context) + String id, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> context) { - MaterialPropertyEditor editor = new MaterialPropertyEditor(id, context); + MaterialPropertyEditor editor = + new MaterialPropertyEditor(id, inputWidgetDescriptions, context); return editor; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertyEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertyEditor.java index d3632452497..db73c45e6e0 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertyEditor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/material/MaterialPropertyEditor.java @@ -16,19 +16,25 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.material; +import java.util.List; +import java.util.Map; + import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; public class MaterialPropertyEditor extends PropertiesEditor<MaterialType, MaterialTypePropertyType> { - public MaterialPropertyEditor(String id, IViewContext<ICommonClientServiceAsync> viewContext) + public MaterialPropertyEditor(String id, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> viewContext) { - super(id, viewContext); + super(id, inputWidgetDescriptions, viewContext); } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java index b234e7b9323..f541d150e71 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/AbstractGenericSampleRegisterEditForm.java @@ -20,6 +20,7 @@ import static ch.systemsx.cisd.openbis.generic.client.web.client.application.fra import java.util.ArrayList; import java.util.List; +import java.util.Map; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.Events; @@ -62,6 +63,7 @@ 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.Space; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.AbstractGenericEntityRegistrationForm; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; @@ -107,16 +109,19 @@ abstract public class AbstractGenericSampleRegisterEditForm extends private Button saveUploadButton; protected AbstractGenericSampleRegisterEditForm( - IViewContext<IGenericClientServiceAsync> viewContext, ActionContext actionContext) + IViewContext<IGenericClientServiceAsync> viewContext, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + ActionContext actionContext) { - this(viewContext, actionContext, null); + this(viewContext, inputWidgetDescriptions, actionContext, null); } protected AbstractGenericSampleRegisterEditForm( - IViewContext<IGenericClientServiceAsync> viewContext, ActionContext actionContext, - IIdAndCodeHolder identifiable) + IViewContext<IGenericClientServiceAsync> viewContext, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + ActionContext actionContext, IIdAndCodeHolder identifiable) { - super(viewContext, identifiable, EntityKind.SAMPLE); + super(viewContext, inputWidgetDescriptions, identifiable, EntityKind.SAMPLE); this.simpleId = createSimpleId(identifiable, EntityKind.SAMPLE); this.attachmentsSessionKey = simpleId + "_attachments"; List<String> sesionKeys = new ArrayList<String>(); @@ -252,9 +257,11 @@ abstract public class AbstractGenericSampleRegisterEditForm extends @Override protected PropertiesEditor<SampleType, SampleTypePropertyType> createPropertiesEditor( - String id, IViewContext<ICommonClientServiceAsync> context) + String id, Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> context) { - SamplePropertyEditor editor = new SamplePropertyEditor(id, context); + SamplePropertyEditor editor = + new SamplePropertyEditor(id, inputWidgetDescriptions, context); return editor; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java index f0ee17240b9..eccc2f860f1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleEditForm.java @@ -57,7 +57,7 @@ public final class GenericSampleEditForm extends AbstractGenericSampleRegisterEd private GenericSampleEditForm(IViewContext<IGenericClientServiceAsync> viewContext, IIdAndCodeHolder identifiable) { - super(viewContext, new ActionContext(), identifiable); + super(viewContext, null, new ActionContext(), identifiable); setRevertButtonVisible(true); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java index 490f37d86a0..022e9e2090f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java @@ -17,6 +17,7 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample; import java.util.List; +import java.util.Map; import ch.systemsx.cisd.common.shared.basic.utils.StringUtils; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ActionContext; @@ -27,6 +28,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientServiceAsync; /** @@ -38,9 +40,10 @@ public final class GenericSampleRegistrationForm extends AbstractGenericSampleRe { public GenericSampleRegistrationForm( final IViewContext<IGenericClientServiceAsync> viewContext, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, final SampleType sampleType, ActionContext actionContext) { - super(viewContext, actionContext); + super(viewContext, inputWidgetDescriptions, actionContext); setResetButtonVisible(true); this.sampleType = sampleType; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SamplePropertyEditor.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SamplePropertyEditor.java index f9584f2fb4a..110164e48c5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SamplePropertyEditor.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/SamplePropertyEditor.java @@ -16,19 +16,24 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample; +import java.util.List; +import java.util.Map; + import ch.systemsx.cisd.openbis.generic.client.web.client.ICommonClientServiceAsync; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; 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.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.experiment.PropertiesEditor; -public class SamplePropertyEditor extends - PropertiesEditor<SampleType, SampleTypePropertyType> +public class SamplePropertyEditor extends PropertiesEditor<SampleType, SampleTypePropertyType> { - public SamplePropertyEditor(String id, IViewContext<ICommonClientServiceAsync> viewContext) + public SamplePropertyEditor(String id, + Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions, + IViewContext<ICommonClientServiceAsync> viewContext) { - super(id, viewContext); + super(id, inputWidgetDescriptions, viewContext); } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluatorTest.java index 59d0b937be0..5ae0dabda5b 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluatorTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/managed_property/ManagedPropertyEvaluatorTest.java @@ -283,59 +283,123 @@ public class ManagedPropertyEvaluatorTest extends AssertJUnit assertEquals(expectedMandatory, widget.isMandatory()); } - @Test + @Test(expectedExceptionsMessageRegExp = "Function updateFromBatchInput is not defined " + + "although function batchColumnNames is defined.", expectedExceptions = EvaluatorException.class) public void testScriptWithBatchColumnNamesFunctionButMissingUpdateFromBatchFunction() { - try - { - new ManagedPropertyEvaluator("def batchColumnNames():\n return ['A']"); - fail("EvaluatorException expected"); - } catch (EvaluatorException ex) - { - assertEquals("Function 'batchColumnNames' defined but not 'updateFromBatchInput'.", - ex.getMessage()); - } + new ManagedPropertyEvaluator("def batchColumnNames():\n return ['A']"); } - @Test + @Test(expectedExceptionsMessageRegExp = "Function updateFromBatchInput is not defined " + + "although function inputWidgets is defined.", expectedExceptions = EvaluatorException.class) + public void testScriptWithInputWidgetsFunctionButMissingUpdateFromBatchFunction() + { + new ManagedPropertyEvaluator( + "def inputWidgets():\n return [inputWidgetFactory().createTextInputField('Field')]"); + } + + @Test(expectedExceptionsMessageRegExp = "Function updateFromBatchInput is not defined " + + "although functions batchColumnNames and inputWidgets are defined.", expectedExceptions = EvaluatorException.class) + public void testScriptWithInputWidgetsFunctionAndBatchColumnNamesFunctionButMissingUpdateFromBatchFunction() + { + new ManagedPropertyEvaluator("def inputWidgets():\n" + + " return [inputWidgetFactory().createTextInputField('Field')]\n" + + "def batchColumnNames():\n return ['A']"); + } + + @Test(expectedExceptionsMessageRegExp = "Function inputWidgets has returned a list " + + "where the 2. element is null.", expectedExceptions = EvaluatorException.class) + public void testScriptWithInputWidgetsFunctionWithANullElement() + { + new ManagedPropertyEvaluator("def inputWidgets():\n" + + " return [inputWidgetFactory().createTextInputField('A'), None]\n" + + "def updateFromBatchInput():\n None"); + } + + @Test(expectedExceptionsMessageRegExp = "Function inputWidgets has returned a list where " + + "the 2. element isn't of type " + + "ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription " + + "but java.lang.String.", expectedExceptions = EvaluatorException.class) + public void testScriptWithInputWidgetsFunctionWithElementOfWrongType() + { + new ManagedPropertyEvaluator("def inputWidgets():\n" + + " return [inputWidgetFactory().createTextInputField('A'), 'B']\n" + + "def updateFromBatchInput():\n None"); + } + + @Test(expectedExceptionsMessageRegExp = "Function 'batchColumnNames' doesn't return a List " + + "but an object of type 'java.lang.Integer': 42", expectedExceptions = EvaluatorException.class) public void testScriptWithBatchColumnNamesFunctionWhichDoesNotReturnAList() { - try - { - new ManagedPropertyEvaluator("def batchColumnNames():\n return 42\n" - + "def updateFromBatchInput():\n None"); - fail("EvaluatorException expected"); - } catch (EvaluatorException ex) - { - assertEquals("Function 'batchColumnNames' doesn't return a List " - + "but an object of type 'java.lang.Integer': 42", ex.getMessage()); - } + new ManagedPropertyEvaluator("def batchColumnNames():\n return 42\n" + + "def updateFromBatchInput():\n None"); } - @Test - public void testScriptWithBatchColumnNamesFunctionWhichReturnLowerCaseNames() + @Test(expectedExceptionsMessageRegExp = "There is already an input widget with code: A", expectedExceptions = EvaluatorException.class) + public void testScriptWithInputWidgetsFunctionWithNonUniqueCodes() { - try - { - new ManagedPropertyEvaluator( - "def batchColumnNames():\n return ['abc', 'A', 'e42', 42]\n" - + "def updateFromBatchInput():\n None"); - fail("EvaluatorException expected"); - } catch (EvaluatorException ex) - { - assertEquals("The following batch column names " - + "as returned by function 'batchColumnNames' " - + "are not in upper case: [abc, e42]", ex.getMessage()); - } + new ManagedPropertyEvaluator("def inputWidgets():\n" + " f = inputWidgetFactory()\n" + + " w1 = f.createTextInputField('a')\n" + " w2 = f.createTextInputField('Alpha')\n" + + " w2.code = 'A'\n" + " return [w1, w2]\n" + "def updateFromBatchInput():\n None"); } @Test public void testGetBatchColumnNamesScript() { ManagedPropertyEvaluator evaluator = - new ManagedPropertyEvaluator("def batchColumnNames():\n return ['A', 42]\n" + new ManagedPropertyEvaluator("def batchColumnNames():\n return ['A', 'Beta']\n" + "def updateFromBatchInput():\n None"); - assertEquals("[A, 42]", evaluator.getBatchColumnNames().toString()); + assertEquals("[A, BETA]", evaluator.getBatchColumnNames().toString()); + List<IManagedInputWidgetDescription> inputWidgetDescriptions = + evaluator.getInputWidgetDescriptions(); + assertEquals("A", inputWidgetDescriptions.get(0).getCode()); + assertEquals("A", inputWidgetDescriptions.get(0).getLabel()); + assertEquals(ManagedInputFieldType.TEXT, inputWidgetDescriptions.get(0) + .getManagedInputFieldType()); + assertEquals("BETA", inputWidgetDescriptions.get(1).getCode()); + assertEquals("Beta", inputWidgetDescriptions.get(1).getLabel()); + assertEquals(ManagedInputFieldType.TEXT, inputWidgetDescriptions.get(1) + .getManagedInputFieldType()); + assertEquals(2, inputWidgetDescriptions.size()); + } + + @Test + public void testGetInputWidgetsScript() + { + ManagedPropertyEvaluator evaluator = + new ManagedPropertyEvaluator( + "def inputWidgets():\n" + + " return [inputWidgetFactory().createComboBoxInputField('Field', ['A', 'B'])]\n" + + "def updateFromBatchInput():\n None"); + assertEquals("[FIELD]", evaluator.getBatchColumnNames().toString()); + List<IManagedInputWidgetDescription> inputWidgetDescriptions = + evaluator.getInputWidgetDescriptions(); + assertEquals("FIELD", inputWidgetDescriptions.get(0).getCode()); + assertEquals("Field", inputWidgetDescriptions.get(0).getLabel()); + assertEquals("[A, B]", + ((ManagedComboBoxInputWidgetDescription) inputWidgetDescriptions.get(0)) + .getOptions().toString()); + assertEquals(1, inputWidgetDescriptions.size()); + } + + @Test + public void testGetInputWidgetsScriptAndBatchColumnNamesScript() + { + ManagedPropertyEvaluator evaluator = + new ManagedPropertyEvaluator( + "def batchColumnNames():\n return ['A', 'Beta']\n" + + "def inputWidgets():\n" + + " return [inputWidgetFactory().createComboBoxInputField('Field', ['A', 'B'])]\n" + + "def updateFromBatchInput():\n None"); + assertEquals("[A, BETA]", evaluator.getBatchColumnNames().toString()); + List<IManagedInputWidgetDescription> inputWidgetDescriptions = + evaluator.getInputWidgetDescriptions(); + assertEquals("FIELD", inputWidgetDescriptions.get(0).getCode()); + assertEquals("Field", inputWidgetDescriptions.get(0).getLabel()); + assertEquals("[A, B]", + ((ManagedComboBoxInputWidgetDescription) inputWidgetDescriptions.get(0)) + .getOptions().toString()); + assertEquals(1, inputWidgetDescriptions.size()); } @Test diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/web/client/application/wizard/BiologicalSampleCreatingPage.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/web/client/application/wizard/BiologicalSampleCreatingPage.java index 71c9a9541e0..770a828280c 100644 --- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/web/client/application/wizard/BiologicalSampleCreatingPage.java +++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/proteomics/client/web/client/application/wizard/BiologicalSampleCreatingPage.java @@ -16,8 +16,10 @@ package ch.systemsx.cisd.openbis.plugin.proteomics.client.web.client.application.wizard; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Map; import com.extjs.gxt.ui.client.event.SelectionChangedEvent; import com.extjs.gxt.ui.client.event.SelectionChangedListener; @@ -42,6 +44,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; 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.api.IManagedInputWidgetDescription; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample.AbstractGenericSampleRegisterEditForm; import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sample.SamplePropertyEditor; import ch.systemsx.cisd.openbis.plugin.proteomics.client.web.client.IPhosphoNetXClientServiceAsync; @@ -63,6 +66,9 @@ public class BiologicalSampleCreatingPage extends WizardPage<MsInjectionSampleAn private SamplePropertyEditor samplePropertyEditor; private ExperimentChooserFieldAdaptor experimentField; + private Map<String, List<IManagedInputWidgetDescription>> inputWidgetDescriptions = Collections + .<String, List<IManagedInputWidgetDescription>> emptyMap(); + public BiologicalSampleCreatingPage(IViewContext<IPhosphoNetXClientServiceAsync> viewContext, MsInjectionSampleAnnotationModel model) { @@ -134,7 +140,9 @@ public class BiologicalSampleCreatingPage extends WizardPage<MsInjectionSampleAn viewContext.getCommonViewContext()); formPanel.add(experimentField.getChooserField()); - samplePropertyEditor = new SamplePropertyEditor("bio-s", viewContext.getCommonViewContext()); + samplePropertyEditor = + new SamplePropertyEditor("bio-s", inputWidgetDescriptions, + viewContext.getCommonViewContext()); samplePropertyEditor.initWithoutProperties(types); samplePropertyEditor.addPropertyFieldsWithFieldsetToPanel(formPanel); formPanel.layout(); -- GitLab