From c23e83d372105132cbe37368964818a4bed3ef3e Mon Sep 17 00:00:00 2001 From: alaskowski <alaskowski@ethz.ch> Date: Wed, 12 Jul 2023 13:36:34 +0200 Subject: [PATCH] SSDM-55: Adding multivalued property handling for Samples --- .../generic/shared/api/v1/dto/Sample.java | 7 +- .../UpdateEntityPropertyExecutor.java | 393 ++++++++++++------ .../property/PropertyTranslator.java | 35 +- .../helper/AbstractXLSExportHelper.java | 2 +- .../PropertyAssignmentImportHelper.java | 3 +- .../helper/PropertyTypeImportHelper.java | 81 +++- .../api/v1/sort/SampleSearchResultSorter.java | 1 + .../samplelister/SampleLister.java | 80 ++-- .../search/sort/IEntitySearchResult.java | 1 + .../sort/SearchResultSorterByScore.java | 17 +- .../generic/shared/dto/DataSetPropertyPE.java | 3 +- .../generic/shared/dto/SamplePropertyPE.java | 3 +- .../sort/SearchResultSorterTestHelper.java | 1 + 13 files changed, 417 insertions(+), 210 deletions(-) diff --git a/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Sample.java b/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Sample.java index acf8d4ff29f..c233660629f 100644 --- a/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Sample.java +++ b/api-openbis-java/source/java/ch/systemsx/cisd/openbis/generic/shared/api/v1/dto/Sample.java @@ -198,7 +198,12 @@ public final class Sample implements Serializable, IIdentifierHolder, IIdHolder public void putProperty(String propCode, String value) { - properties.put(propCode, value); + if(properties.containsKey(propCode)) { + properties.put(propCode, properties.get(propCode) + ", " + value); + } else + { + properties.put(propCode, value); + } } public List<Metaproject> getMetaprojects() diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/UpdateEntityPropertyExecutor.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/UpdateEntityPropertyExecutor.java index cb5b2fb7c1b..59d6f11f15f 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/UpdateEntityPropertyExecutor.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/property/UpdateEntityPropertyExecutor.java @@ -16,14 +16,8 @@ package ch.ethz.sis.openbis.generic.server.asapi.v3.executor.property; import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; @@ -77,7 +71,7 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut @Autowired private IManagedPropertyEvaluatorFactory managedPropertyEvaluatorFactory; - + @Autowired private IMapSampleByIdExecutor mapSampleByIdExecutor; @@ -89,7 +83,8 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut { } - public UpdateEntityPropertyExecutor(IDAOFactory daoFactory, IManagedPropertyEvaluatorFactory managedPropertyEvaluatorFactory) + public UpdateEntityPropertyExecutor(IDAOFactory daoFactory, + IManagedPropertyEvaluatorFactory managedPropertyEvaluatorFactory) { this.daoFactory = daoFactory; this.managedPropertyEvaluatorFactory = managedPropertyEvaluatorFactory; @@ -99,7 +94,8 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut public void update(final IOperationContext context, final MapBatch<? extends IPropertiesHolder, ? extends IEntityInformationWithPropertiesHolder> holderToEntityMap) { - final MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> entityToPropertiesMap = + final MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> + entityToPropertiesMap = getEntityToPropertiesMap(holderToEntityMap); if (entityToPropertiesMap == null || entityToPropertiesMap.isEmpty()) @@ -107,117 +103,170 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut return; } - MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> entityToSamplePropertiesMap = + MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> + entityToSamplePropertiesMap = extractAndRemoveSampleProperties(holderToEntityMap, entityToPropertiesMap); updateSampleProps(context, entityToSamplePropertiesMap); - final Map<EntityKind, EntityPropertiesConverter> converters = new HashMap<EntityKind, EntityPropertiesConverter>(); + final Map<EntityKind, EntityPropertiesConverter> converters = + new HashMap<EntityKind, EntityPropertiesConverter>(); - new MapBatchProcessor<IEntityInformationWithPropertiesHolder, Map<String, Serializable>>(context, entityToPropertiesMap) + new MapBatchProcessor<IEntityInformationWithPropertiesHolder, Map<String, Serializable>>( + context, entityToPropertiesMap) + { + @Override + public void process(IEntityInformationWithPropertiesHolder propertiesHolder, + Map<String, Serializable> properties) { - @Override - public void process(IEntityInformationWithPropertiesHolder propertiesHolder, Map<String, Serializable> properties) - { - EntityKind entityKind = propertiesHolder.getEntityType().getEntityKind(); - - if (converters.get(entityKind) == null) - { - EntityPropertiesConverter converter = - new EntityPropertiesConverter(entityKind, daoFactory, entityInformationProvider, managedPropertyEvaluatorFactory); - converters.put(entityKind, converter); - } - - update(context, propertiesHolder, properties, converters.get(entityKind)); - } + EntityKind entityKind = propertiesHolder.getEntityType().getEntityKind(); - @Override - public IProgress createProgress(IEntityInformationWithPropertiesHolder propertiesHolder, - Map<String, Serializable> properties, - int objectIndex, int totalObjectCount) + if (converters.get(entityKind) == null) { - return new UpdatePropertyProgress(propertiesHolder, properties, objectIndex, totalObjectCount); + EntityPropertiesConverter converter = + new EntityPropertiesConverter(entityKind, daoFactory, + entityInformationProvider, managedPropertyEvaluatorFactory); + converters.put(entityKind, converter); } - }; + + update(context, propertiesHolder, properties, converters.get(entityKind)); + } + + @Override + public IProgress createProgress(IEntityInformationWithPropertiesHolder propertiesHolder, + Map<String, Serializable> properties, + int objectIndex, int totalObjectCount) + { + return new UpdatePropertyProgress(propertiesHolder, properties, objectIndex, + totalObjectCount); + } + }; } private void updateSampleProps(IOperationContext context, - MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> entityToSamplePropertiesMap) + MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> entityToSamplePropertiesMap) { if (entityToSamplePropertiesMap != null && entityToSamplePropertiesMap.isEmpty() == false) { Map<ISampleId, SamplePE> samplesById = getSamples(context, entityToSamplePropertiesMap); - new MapBatchProcessor<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>>(context, entityToSamplePropertiesMap) + new MapBatchProcessor<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>>( + context, entityToSamplePropertiesMap) + { + @Override + public void process(IEntityInformationWithPropertiesHolder entity, + Map<String, ISampleId[]> properties) { - @Override - public void process(IEntityInformationWithPropertiesHolder entity, Map<String, ISampleId> properties) - { - Map<String, EntityPropertyPE> existingPropertiesByCode = getExistingPropertiesByCode(entity); - Map<String, EntityTypePropertyTypePE> entityTypePropertyTypeByPropertyType = - getEntityTypePropertyTypeByPropertyType(entity); - updateProperties(context, entity, properties, samplesById, existingPropertiesByCode, - entityTypePropertyTypeByPropertyType); - } + Map<String, List<EntityPropertyPE>> existingPropertiesByCode = + getExistingPropertiesByCode(entity); + Map<String, EntityTypePropertyTypePE> entityTypePropertyTypeByPropertyType = + getEntityTypePropertyTypeByPropertyType(entity); + updateProperties(context, entity, properties, samplesById, + existingPropertiesByCode, + entityTypePropertyTypeByPropertyType); + } - @Override - public IProgress createProgress(IEntityInformationWithPropertiesHolder key, Map<String, ISampleId> value, int objectIndex, - int totalObjectCount) - { - return new EntityProgress("update properties of type sample", key, objectIndex, totalObjectCount); - } - }; + @Override + public IProgress createProgress(IEntityInformationWithPropertiesHolder key, + Map<String, ISampleId[]> value, int objectIndex, + int totalObjectCount) + { + return new EntityProgress("update properties of type sample", key, objectIndex, + totalObjectCount); + } + }; } } - private void updateProperties(final IOperationContext context, IEntityInformationWithPropertiesHolder entity, - Map<String, ISampleId> properties, Map<ISampleId, SamplePE> samplesById, - Map<String, EntityPropertyPE> existingPropertiesByCode, + private void updateProperties(final IOperationContext context, + IEntityInformationWithPropertiesHolder entity, + Map<String, ISampleId[]> properties, Map<ISampleId, SamplePE> samplesById, + Map<String, List<EntityPropertyPE>> existingPropertiesByCode, Map<String, EntityTypePropertyTypePE> entityTypePropertyTypeByPropertyType) { - for (Entry<String, ISampleId> property : properties.entrySet()) + for (Entry<String, ISampleId[]> property : properties.entrySet()) { String propertyCode = property.getKey(); EntityTypePropertyTypePE etpt = entityTypePropertyTypeByPropertyType.get(propertyCode); if (etpt == null) { - throw new UserFailureException("Not a property of data type SAMPLE: " + propertyCode); + throw new UserFailureException( + "Not a property of data type SAMPLE: " + propertyCode); } - EntityPropertyPE existingProperty = existingPropertiesByCode.get(propertyCode); - ISampleId sampleId = property.getValue(); - SamplePE sample = validateAndGetSample(samplesById, sampleId, etpt, propertyCode); - if (existingProperty != null) - { - if (sample == null) - { - if (existingProperty.getEntityTypePropertyType().isMandatory() == false) - { - entity.removeProperty(existingProperty); - } else - { - throw new UserFailureException("Property " + propertyCode + " of entity type " - + etpt.getEntityType().getCode() - + " can not be deleted because it is mandatory."); - } - } else if (existingProperty instanceof EntityPropertyWithSampleDataTypePE) - { - ((EntityPropertyWithSampleDataTypePE) existingProperty).setSampleValue(sample); + List<EntityPropertyPE> existingProperties = existingPropertiesByCode.getOrDefault(propertyCode, new ArrayList<>()); + ISampleId[] sampleIds = property.getValue(); + + if(sampleIds.length > 1 && !etpt.getPropertyType().isMultiValue()) { + throw new UserFailureException("Property " + propertyCode + " of entity type " + + etpt.getEntityType().getCode() + + " is a single-value property. It can not accept multiple values."); + } + + if(sampleIds.length == 1 && sampleIds[0] == null) { + if (etpt.isMandatory()) { + throw new UserFailureException( + "Property " + propertyCode + " of entity type " + + etpt.getEntityType().getCode() + + " can not be deleted because it is mandatory."); } - } else if (sample != null) - { - EntityPropertyPE entityProperty = EntityPropertyPE.createEntityProperty(entity.getEntityKind()); - if (entityProperty instanceof EntityPropertyWithSampleDataTypePE) - { - PersonPE registrator = context.getSession().tryGetPerson(); - entityProperty.setRegistrator(registrator); - entityProperty.setAuthor(registrator); - entityProperty.setEntityTypePropertyType(etpt); - ((EntityPropertyWithSampleDataTypePE) entityProperty).setSampleValue(sample); - entity.addProperty(entityProperty); + existingProperties.forEach(entity::removeProperty); + continue; + } + + List<EntityPropertyPE> newProperties = new ArrayList<>(); + for (ISampleId sampleId : sampleIds) { + SamplePE sample = validateAndGetSample(samplesById, sampleId, etpt, propertyCode); + if(sample != null) { + EntityPropertyWithSampleDataTypePE existingProperty = null; + for(EntityPropertyPE propertyPE : existingProperties) { + EntityPropertyWithSampleDataTypePE prop = (EntityPropertyWithSampleDataTypePE) propertyPE; + if(prop.getSampleValue().getPermId().equals(sample.getPermId())) { + existingProperty = prop; + break; + } + } + + if(existingProperty != null) { + existingProperty.setSampleValue(sample); + newProperties.add(existingProperty); + } else { + EntityPropertyPE entityProperty = + EntityPropertyPE.createEntityProperty(entity.getEntityKind()); + if (entityProperty instanceof EntityPropertyWithSampleDataTypePE) + { + PersonPE registrator = context.getSession().tryGetPerson(); + entityProperty.setRegistrator(registrator); + entityProperty.setAuthor(registrator); + entityProperty.setEntityTypePropertyType(etpt); + ((EntityPropertyWithSampleDataTypePE) entityProperty).setSampleValue( + sample); + } + newProperties.add(entityProperty); + } + } else { + throw new UserFailureException("Sample " + sampleId + " Does not exists!"); } + } + + if(!newProperties.isEmpty()) { + existingProperties.forEach(entity::removeProperty); + newProperties.forEach(entity::addProperty); + } + + } + } + + private EntityPropertyPE tryFindSampleProperty(List<EntityPropertyPE> properties, SamplePE sample) { + if(sample == null || properties == null) { + return null; } + return properties.stream() + .filter(x -> x.getEntity().getCode().equals(sample.getCode())) + .findFirst() + .orElse(null); } - private SamplePE validateAndGetSample(Map<ISampleId, SamplePE> samplesById, ISampleId sampleId, EntityTypePropertyTypePE etpt, + private SamplePE validateAndGetSample(Map<ISampleId, SamplePE> samplesById, ISampleId sampleId, + EntityTypePropertyTypePE etpt, String propertyCode) { if (sampleId == null) @@ -230,7 +279,8 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut throw new UserFailureException("Unknown sample: " + sampleId); } SampleTypePE sampleType = etpt.getPropertyType().getSampleType(); - if (sampleType != null && sampleType.getCode().equals(sample.getSampleType().getCode()) == false) + if (sampleType != null && sampleType.getCode() + .equals(sample.getSampleType().getCode()) == false) { throw new UserFailureException("Property " + propertyCode + " is not a sample of type " + sampleType.getCode() + " but of type " + sample.getSampleType().getCode()); @@ -238,20 +288,25 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut return sample; } - private Map<String, EntityPropertyPE> getExistingPropertiesByCode(IEntityInformationWithPropertiesHolder entity) + private Map<String, List<EntityPropertyPE>> getExistingPropertiesByCode( + IEntityInformationWithPropertiesHolder entity) { - Map<String, EntityPropertyPE> existingPropertiesByCode = new HashMap<>(); + Map<String, List<EntityPropertyPE>> existingPropertiesByCode = new HashMap<>(); for (EntityPropertyPE entityProperty : entity.getProperties()) { - PropertyTypePE propertyType = entityProperty.getEntityTypePropertyType().getPropertyType(); - existingPropertiesByCode.put(propertyType.getCode(), entityProperty); + String propertyCode = + entityProperty.getEntityTypePropertyType().getPropertyType().getCode(); + existingPropertiesByCode.computeIfAbsent(propertyCode, s -> new ArrayList<>()); + existingPropertiesByCode.get(propertyCode).add(entityProperty); } return existingPropertiesByCode; } - private Map<String, EntityTypePropertyTypePE> getEntityTypePropertyTypeByPropertyType(IEntityInformationWithPropertiesHolder entity) + private Map<String, EntityTypePropertyTypePE> getEntityTypePropertyTypeByPropertyType( + IEntityInformationWithPropertiesHolder entity) { - Map<String, EntityTypePropertyTypePE> entityTypePropertyTypeByPropertyType = new HashMap<>(); + Map<String, EntityTypePropertyTypePE> entityTypePropertyTypeByPropertyType = + new HashMap<>(); for (EntityTypePropertyTypePE etpt : entity.getEntityType().getEntityTypePropertyTypes()) { PropertyTypePE propertyType = etpt.getPropertyType(); @@ -264,43 +319,52 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut } private Map<ISampleId, SamplePE> getSamples(final IOperationContext context, - MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> entityToSamplePropertiesMap) + MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> entityToSamplePropertiesMap) { Set<ISampleId> sampleIds = getSampleIds(entityToSamplePropertiesMap); Map<ISampleId, SamplePE> samplesById = mapSampleByIdExecutor.map(context, sampleIds); - Set<Long> validateSampleTechIds = sampleAuthorizationValidator.validate(context.getSession().tryGetPerson(), - samplesById.values().stream().map(SamplePE::getId).collect(Collectors.toSet())); - return samplesById.entrySet().stream().filter(e -> validateSampleTechIds.contains(e.getValue().getId())) + Set<Long> validateSampleTechIds = + sampleAuthorizationValidator.validate(context.getSession().tryGetPerson(), + samplesById.values().stream().map(SamplePE::getId) + .collect(Collectors.toSet())); + return samplesById.entrySet().stream() + .filter(e -> validateSampleTechIds.contains(e.getValue().getId())) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - private Set<ISampleId> getSampleIds(MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> entityToSamplePropertiesMap) + private Set<ISampleId> getSampleIds( + MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> entityToSamplePropertiesMap) { Set<ISampleId> sampleIds = new HashSet<>(); - for (Map<String, ISampleId> map : entityToSamplePropertiesMap.getObjects().values()) + for (Map<String, ISampleId[]> map : entityToSamplePropertiesMap.getObjects().values()) { - Collection<ISampleId> values = map.values(); - for (ISampleId sample : values) + Collection<ISampleId[]> values = map.values(); + for (ISampleId[] samples : values) { - if (sample != null) + for (ISampleId sample : samples) { - sampleIds.add(sample); + if (sample != null) + { + sampleIds.add(sample); + } } } } return sampleIds; } - private MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> extractAndRemoveSampleProperties( + private MapBatch<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> extractAndRemoveSampleProperties( MapBatch<? extends IPropertiesHolder, ? extends IEntityInformationWithPropertiesHolder> holderToEntityMap, MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> entityToPropertiesMap) { - Map<IEntityInformationWithPropertiesHolder, Map<String, ISampleId>> map = new HashMap<>(); - Map<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> objects = entityToPropertiesMap.getObjects(); + Map<IEntityInformationWithPropertiesHolder, Map<String, ISampleId[]>> map = new HashMap<>(); + Map<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> objects = + entityToPropertiesMap.getObjects(); for (Entry<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> entry : objects.entrySet()) { IEntityInformationWithPropertiesHolder entity = entry.getKey(); - Collection<? extends EntityTypePropertyTypePE> etpts = entity.getEntityType().getEntityTypePropertyTypes(); + Collection<? extends EntityTypePropertyTypePE> etpts = + entity.getEntityType().getEntityTypePropertyTypes(); for (EntityTypePropertyTypePE etpt : etpts) { @@ -310,27 +374,50 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut Map<String, Serializable> properties = entry.getValue(); if (properties.containsKey(code)) { - String sample = (String) properties.remove(code); - ISampleId sampleId = null; - if (sample != null) + Serializable value = properties.remove(code); + ISampleId[] samples; + if (value != null && value.getClass().isArray()) + { + List<ISampleId> tmp = new ArrayList<>(); + for (Serializable sample : (Serializable[]) value) + { + tmp.add(getSampleFromProperty(sample)); + } + samples = tmp.toArray(new ISampleId[0]); + } else { - sampleId = sample.startsWith("/") ? new SampleIdentifier(sample) : new SamplePermId(sample); + samples = new ISampleId[] { getSampleFromProperty(value) }; } - Map<String, ISampleId> props = map.get(entity); + + Map<String, ISampleId[]> props = map.get(entity); if (props == null) { props = new HashMap<>(); map.put(entity, props); } - props.put(code, sampleId); + props.put(code, samples); } } } } - return new MapBatch<>(holderToEntityMap.getBatchIndex(), holderToEntityMap.getFromObjectIndex(), + return new MapBatch<>(holderToEntityMap.getBatchIndex(), + holderToEntityMap.getFromObjectIndex(), holderToEntityMap.getToObjectIndex(), map, holderToEntityMap.getTotalObjectCount()); } + private ISampleId getSampleFromProperty(Serializable sampleProperty) + { + String sample = (String) sampleProperty; + ISampleId sampleId = null; + if (sample != null) + { + sampleId = sample.startsWith("/") ? + new SampleIdentifier(sample) : + new SamplePermId(sample); + } + return sampleId; + } + private MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> getEntityToPropertiesMap( final MapBatch<? extends IPropertiesHolder, ? extends IEntityInformationWithPropertiesHolder> holderToEntityMap) { @@ -339,7 +426,8 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut return null; } - Map<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> entityToPropertiesMap = + Map<IEntityInformationWithPropertiesHolder, Map<String, Serializable>> + entityToPropertiesMap = new HashMap<>(); for (Map.Entry<? extends IPropertiesHolder, ? extends IEntityInformationWithPropertiesHolder> entry : holderToEntityMap.getObjects() @@ -359,12 +447,15 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut return null; } - return new MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>>(holderToEntityMap.getBatchIndex(), - holderToEntityMap.getFromObjectIndex(), holderToEntityMap.getToObjectIndex(), entityToPropertiesMap, + return new MapBatch<IEntityInformationWithPropertiesHolder, Map<String, Serializable>>( + holderToEntityMap.getBatchIndex(), + holderToEntityMap.getFromObjectIndex(), holderToEntityMap.getToObjectIndex(), + entityToPropertiesMap, holderToEntityMap.getTotalObjectCount()); } - private void update(IOperationContext context, IEntityPropertiesHolder propertiesHolder, Map<String, Serializable> properties, + private void update(IOperationContext context, IEntityPropertiesHolder propertiesHolder, + Map<String, Serializable> properties, EntityPropertiesConverter converter) { List<IEntityProperty> entityProperties = new LinkedList<IEntityProperty>(); @@ -374,26 +465,30 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut } Set<? extends EntityPropertyPE> existingProperties = propertiesHolder.getProperties(); - Map<String, Object> existingPropertyValuesByCode = new HashMap<String, Object>(); - + Map<String, List<Object>> existingPropertyValuesByCode = + new HashMap<String, List<Object>>(); for (EntityPropertyPE existingProperty : existingProperties) { String propertyCode = existingProperty.getEntityTypePropertyType().getPropertyType().getCode(); - existingPropertyValuesByCode.put(propertyCode, getValue(existingProperty)); + existingPropertyValuesByCode.computeIfAbsent(propertyCode, s -> new ArrayList<>()); + existingPropertyValuesByCode.get(propertyCode).add(getValue(existingProperty)); } Set<? extends EntityPropertyPE> convertedProperties = - convertProperties(context, propertiesHolder.getEntityType(), existingProperties, entityProperties, converter); + convertProperties(context, propertiesHolder.getEntityType(), existingProperties, + entityProperties, converter); - if (isEquals(existingPropertyValuesByCode, convertedProperties) == false) + if (isEqualsMultiple(existingPropertyValuesByCode, convertedProperties) == false) { propertiesHolder.setProperties(convertedProperties); } } - private <T extends EntityPropertyPE> Set<T> convertProperties(IOperationContext context, final EntityTypePE type, - final Set<T> existingProperties, List<IEntityProperty> properties, EntityPropertiesConverter converter) + private <T extends EntityPropertyPE> Set<T> convertProperties(IOperationContext context, + final EntityTypePE type, + final Set<T> existingProperties, List<IEntityProperty> properties, + EntityPropertiesConverter converter) { Set<String> propertiesToUpdate = new HashSet<String>(); if (properties != null) @@ -438,4 +533,50 @@ public class UpdateEntityPropertyExecutor implements IUpdateEntityPropertyExecut return existingPropertyValuesByCode.isEmpty(); } + private boolean isEqualsMultiple(Map<String, List<Object>> existingPropertyValuesByCode, + Set<? extends EntityPropertyPE> properties) + { + for (EntityPropertyPE property : properties) + { + List<Object> existingValueList = + existingPropertyValuesByCode.get(property.getEntityTypePropertyType() + .getPropertyType().getCode()); + if (existingValueList == null || existingValueList.isEmpty()) + { + return false; + } + boolean flag = false; + Object valToRemove = null; + for (Object value : existingValueList) + { + Object propertyValue = getValue(property); + if (propertyValue == null) + { + // TODO: Add logic for sample property + // we have some non-EntityPropertyPE property. + return false; + } + if (value.equals(propertyValue)) + { + flag = true; + valToRemove = value; + break; + } + } + if (flag) + { + existingValueList.remove(valToRemove); + if (existingValueList.isEmpty()) + { + existingPropertyValuesByCode.remove(property.getEntityTypePropertyType() + .getPropertyType().getCode()); + } + } else + { + return false; + } + } + return existingPropertyValuesByCode.isEmpty(); + } + } diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTranslator.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTranslator.java index 9867b6bba97..bc908803a2b 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTranslator.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/translator/property/PropertyTranslator.java @@ -78,17 +78,8 @@ public abstract class PropertyTranslator extends { if(objectProperties.containsKey(record.propertyCode)) { Serializable current = objectProperties.get(record.propertyCode); - Serializable[] vocabs; - if(current.getClass().isArray()) { - Serializable[] values = (Serializable[]) current; - vocabs = new Serializable[values.length + 1]; - System.arraycopy(values, 0, vocabs, 0, values.length); - vocabs[values.length] = record.vocabularyPropertyValue; - } else { - vocabs = new Serializable[] {current, record.vocabularyPropertyValue}; - } - objectProperties.put(record.propertyCode, vocabs); - + Serializable newValue = composeMultiValueProperty(current, record.vocabularyPropertyValue); + objectProperties.put(record.propertyCode, newValue); } else { objectProperties.put(record.propertyCode, record.vocabularyPropertyValue); } @@ -96,7 +87,14 @@ public abstract class PropertyTranslator extends { if (visibaleSamples.contains(record.sample_id)) { - objectProperties.put(record.propertyCode, record.sample_perm_id); + if(objectProperties.containsKey(record.propertyCode)) { + Serializable current = objectProperties.get(record.propertyCode); + Serializable newValue = composeMultiValueProperty(current, record.sample_perm_id); + objectProperties.put(record.propertyCode, newValue); + } else + { + objectProperties.put(record.propertyCode, record.sample_perm_id); + } } } else if (record.integerArrayPropertyValue != null) { @@ -126,6 +124,19 @@ public abstract class PropertyTranslator extends return properties; } + private Serializable composeMultiValueProperty(Serializable current, Serializable newValue) { + Serializable[] result; + if(current.getClass().isArray()) { + Serializable[] values = (Serializable[]) current; + result = new Serializable[values.length + 1]; + System.arraycopy(values, 0, result, 0, values.length); + result[values.length] = newValue; + } else { + result = new Serializable[] {current, newValue}; + } + return result; + } + private String convertArrayToString(String[] array) { return Stream.of(array) diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/export/helper/AbstractXLSExportHelper.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/export/helper/AbstractXLSExportHelper.java index 9052b96c808..a441db2f1bd 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/export/helper/AbstractXLSExportHelper.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/export/helper/AbstractXLSExportHelper.java @@ -49,7 +49,7 @@ public abstract class AbstractXLSExportHelper<ENTITY_TYPE extends IEntityType> i protected static final String[] ENTITY_ASSIGNMENT_COLUMNS = new String[] { "Version", "Code", "Mandatory", "Show in edit views", "Section", "Property label", "Data type", "Vocabulary code", "Description", - "Metadata", "Dynamic script" }; + "Metadata", "Dynamic script", "Multivalued" }; protected static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(BasicConstant.DATE_HOURS_MINUTES_SECONDS_PATTERN); diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyAssignmentImportHelper.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyAssignmentImportHelper.java index 507464ab8d7..bf22e1a7aa5 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyAssignmentImportHelper.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyAssignmentImportHelper.java @@ -69,7 +69,8 @@ public class PropertyAssignmentImportHelper extends BasicImportHelper DynamicScript("Dynamic script", false), OntologyId("Ontology Id", false), OntologyVersion("Ontology Version", false), - OntologyAnnotationId("Ontology Annotation Id", false); + OntologyAnnotationId("Ontology Annotation Id", false), + MultiValued("Multivalued", false),; private final String headerName; diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyTypeImportHelper.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyTypeImportHelper.java index 4ba863ad085..dfda7051787 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyTypeImportHelper.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/xls/importer/helper/PropertyTypeImportHelper.java @@ -47,13 +47,16 @@ import static ch.ethz.sis.openbis.generic.server.xls.importer.utils.PropertyType public class PropertyTypeImportHelper extends BasicImportHelper { - private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, PropertyTypeImportHelper.class); + private static final Logger operationLog = + LogFactory.getLogger(LogCategory.OPERATION, PropertyTypeImportHelper.class); - private enum Attribute implements IAttribute { + private enum Attribute implements IAttribute + { Version("Version", true), Code("Code", true), Mandatory("Mandatory", false), - DefaultValue("Default Value", false), // Ignored, only used by PropertyAssignmentImportHelper + DefaultValue("Default Value", + false), // Ignored, only used by PropertyAssignmentImportHelper ShowInEditViews("Show in edit views", false), Section("Section", false), PropertyLabel("Property label", true), @@ -64,21 +67,26 @@ public class PropertyTypeImportHelper extends BasicImportHelper DynamicScript("Dynamic script", false), OntologyId("Ontology Id", false), OntologyVersion("Ontology Version", false), - OntologyAnnotationId("Ontology Annotation Id", false); + OntologyAnnotationId("Ontology Annotation Id", false), + MultiValued("Multivalued", false); private final String headerName; private final boolean mandatory; - Attribute(String headerName, boolean mandatory) { + Attribute(String headerName, boolean mandatory) + { this.headerName = headerName; this.mandatory = mandatory; } - public String getHeaderName() { + public String getHeaderName() + { return headerName; } - public boolean isMandatory() { + + public boolean isMandatory() + { return mandatory; } } @@ -91,7 +99,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper private final AttributeValidator<Attribute> attributeValidator; - public PropertyTypeImportHelper(DelayedExecutionDecorator delayedExecutor, ImportModes mode, ImportOptions options, Map<String, Integer> versions) + public PropertyTypeImportHelper(DelayedExecutionDecorator delayedExecutor, ImportModes mode, + ImportOptions options, Map<String, Integer> versions) { super(mode, options); this.versions = versions; @@ -101,7 +110,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper } @Override - protected void validateLine(Map<String, Integer> headers, List<String> values) { + protected void validateLine(Map<String, Integer> headers, List<String> values) + { // Validate Unambiguous String code = getValueByColumnName(headers, values, Attribute.Code); String propertyLabel = getValueByColumnName(headers, values, Attribute.PropertyLabel); @@ -110,31 +120,37 @@ public class PropertyTypeImportHelper extends BasicImportHelper String vocabularyCode = getValueByColumnName(headers, values, Attribute.VocabularyCode); String metadata = getValueByColumnName(headers, values, Attribute.Metadata); - String propertyData = code + propertyLabel + description + dataType + vocabularyCode + metadata; + String propertyData = + code + propertyLabel + description + dataType + vocabularyCode + metadata; if (this.propertyCache.get(code) == null) { this.propertyCache.put(code, propertyData); } if (!propertyData.equals(this.propertyCache.get(code))) { - throw new UserFailureException("Unambiguous property " + code + " found, has been declared before with different attributes."); + throw new UserFailureException( + "Unambiguous property " + code + " found, has been declared before with different attributes."); } } - @Override protected ImportTypes getTypeName() + @Override + protected ImportTypes getTypeName() { return ImportTypes.PROPERTY_TYPE; } - @Override protected boolean isNewVersion(Map<String, Integer> header, List<String> values) + @Override + protected boolean isNewVersion(Map<String, Integer> header, List<String> values) { String newVersion = getValueByColumnName(header, values, Attribute.Version); String code = getValueByColumnName(header, values, Attribute.Code); - return VersionUtils.isNewVersion(newVersion, VersionUtils.getStoredVersion(versions, ImportTypes.PROPERTY_TYPE.getType(), code)); + return VersionUtils.isNewVersion(newVersion, + VersionUtils.getStoredVersion(versions, ImportTypes.PROPERTY_TYPE.getType(), code)); } - @Override protected void updateVersion(Map<String, Integer> header, List<String> values) + @Override + protected void updateVersion(Map<String, Integer> header, List<String> values) { String version = getValueByColumnName(header, values, Attribute.Version); String code = getValueByColumnName(header, values, Attribute.Code); @@ -142,7 +158,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper VersionUtils.updateVersion(version, versions, ImportTypes.PROPERTY_TYPE.getType(), code); } - @Override protected boolean isObjectExist(Map<String, Integer> header, List<String> values) + @Override + protected boolean isObjectExist(Map<String, Integer> header, List<String> values) { String code = getValueByColumnName(header, values, Attribute.Code); PropertyTypeFetchOptions fetchOptions = new PropertyTypeFetchOptions(); @@ -152,7 +169,9 @@ public class PropertyTypeImportHelper extends BasicImportHelper return delayedExecutor.getPropertyType(propertyTypePermId, fetchOptions) != null; } - @Override protected void createObject(Map<String, Integer> header, List<String> values, int page, int line) + @Override + protected void createObject(Map<String, Integer> header, List<String> values, int page, + int line) { String code = getValueByColumnName(header, values, Attribute.Code); String propertyLabel = getValueByColumnName(header, values, Attribute.PropertyLabel); @@ -160,6 +179,7 @@ public class PropertyTypeImportHelper extends BasicImportHelper String dataType = getValueByColumnName(header, values, Attribute.DataType); String vocabularyCode = getValueByColumnName(header, values, Attribute.VocabularyCode); String metadata = getValueByColumnName(header, values, Attribute.Metadata); + String multiValued = getValueByColumnName(header, values, Attribute.MultiValued); PropertyTypeCreation creation = new PropertyTypeCreation(); creation.setCode(code); @@ -169,7 +189,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper if (dataType.startsWith(SAMPLE_DATA_TYPE_PREFIX)) { creation.setDataType(DataType.SAMPLE); - if (dataType.contains(SAMPLE_DATA_TYPE_MANDATORY_TYPE)) { + if (dataType.contains(SAMPLE_DATA_TYPE_MANDATORY_TYPE)) + { String sampleType = dataType.split(SAMPLE_DATA_TYPE_MANDATORY_TYPE)[1]; creation.setSampleTypeId(new EntityTypePermId(sampleType, EntityKind.SAMPLE)); } @@ -188,10 +209,20 @@ public class PropertyTypeImportHelper extends BasicImportHelper creation.setMetaData(JSONHandler.parseMetaData(metadata)); } + if (multiValued != null && !multiValued.isEmpty()) + { + creation.setMultiValue(Boolean.parseBoolean(multiValued)); + } else + { + creation.setMultiValue(false); + } + delayedExecutor.createPropertyType(creation, page, line); } - @Override protected void updateObject(Map<String, Integer> header, List<String> values, int page, int line) + @Override + protected void updateObject(Map<String, Integer> header, List<String> values, int page, + int line) { String code = getValueByColumnName(header, values, Attribute.Code); String propertyLabel = getValueByColumnName(header, values, Attribute.PropertyLabel); @@ -228,12 +259,14 @@ public class PropertyTypeImportHelper extends BasicImportHelper PropertyTypeFetchOptions propertyTypeFetchOptions = new PropertyTypeFetchOptions(); propertyTypeFetchOptions.withVocabulary(); propertyTypeFetchOptions.withSampleType(); - PropertyType propertyType = delayedExecutor.getPropertyType(propertyTypePermId, propertyTypeFetchOptions); + PropertyType propertyType = + delayedExecutor.getPropertyType(propertyTypePermId, propertyTypeFetchOptions); if (vocabularyCode != null && !vocabularyCode.isEmpty()) { if (vocabularyCode.equals(propertyType.getVocabulary().getCode()) == false) { - operationLog.warn("PROPERTY TYPE [" + code+ "] : Vocabulary types can't be updated. Ignoring the update."); + operationLog.warn( + "PROPERTY TYPE [" + code + "] : Vocabulary types can't be updated. Ignoring the update."); // throw new UserFailureException("Vocabulary types can't be updated."); } } @@ -246,7 +279,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper } if (dataType.equals(currentDataType) == false) { - operationLog.warn("PROPERTY TYPE [" + code + "] : Data Types can't be converted with Master Data XLS. Ignoring the update."); + operationLog.warn( + "PROPERTY TYPE [" + code + "] : Data Types can't be converted with Master Data XLS. Ignoring the update."); // update.convertToDataType(DataType.valueOf(dataType)); } } @@ -257,7 +291,8 @@ public class PropertyTypeImportHelper extends BasicImportHelper delayedExecutor.updatePropertyType(update, page, line); } - @Override protected void validateHeader(Map<String, Integer> headers) + @Override + protected void validateHeader(Map<String, Integer> headers) { attributeValidator.validateHeaders(Attribute.values(), headers); } diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/sort/SampleSearchResultSorter.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/sort/SampleSearchResultSorter.java index 6495e1ad986..e1fbc4b9f31 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/sort/SampleSearchResultSorter.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/api/v1/sort/SampleSearchResultSorter.java @@ -15,6 +15,7 @@ */ package ch.systemsx.cisd.openbis.generic.server.api.v1.sort; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java index 84da811402e..1afb97ab4e5 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo.fetchoptions.samplel import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -54,41 +55,41 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; public class SampleLister implements ISampleLister { private static final Comparator<Sample> SAMPLE_COMPARATOR = new Comparator<Sample>() + { + @Override + public int compare(Sample s1, Sample s2) { - @Override - public int compare(Sample s1, Sample s2) - { - return s1.getIdentifier().compareTo(s2.getIdentifier()); - } - }; + return s1.getIdentifier().compareTo(s2.getIdentifier()); + } + }; private static final Comparator<SampleRecord> SAMPLE_COMPARATOR2 = new Comparator<SampleRecord>() + { + @Override + public int compare(SampleRecord s1, SampleRecord s2) { - @Override - public int compare(SampleRecord s1, SampleRecord s2) - { - return getIdentifier(s1).compareTo(getIdentifier(s2)); - } + return getIdentifier(s1).compareTo(getIdentifier(s2)); + } - private String getIdentifier(SampleRecord sampleRecord) - { - String spaceCode = sampleRecord.sp_code; - String sampleCode = sampleRecord.s_code; - return spaceCode == null ? "/" + sampleCode : "/" + spaceCode + "/" - + sampleCode; - } - }; + private String getIdentifier(SampleRecord sampleRecord) + { + String spaceCode = sampleRecord.sp_code; + String sampleCode = sampleRecord.s_code; + return spaceCode == null ? "/" + sampleCode : "/" + spaceCode + "/" + + sampleCode; + } + }; private static final IKeyExtractor<Long, SampleRecord> ID_EXTRACTOR = new IKeyExtractor<Long, SampleRecord>() + { + @Override + public Long getKey(SampleRecord s) { - @Override - public Long getKey(SampleRecord s) - { - return s.s_id; - } - }; + return s.s_id; + } + }; private final ISampleListingQuery query; @@ -300,7 +301,13 @@ public class SampleLister implements ISampleLister { sampleRecord.properties = new HashMap<String, String>(); } - sampleRecord.properties.put(propertyRecord.code, propertyRecord.getValue()); + String value = propertyRecord.getValue(); + if (sampleRecord.properties.containsKey(propertyRecord.code)) + { + String ss = sampleRecord.properties.get(propertyRecord.code); + value = ss + ", " + value; + } + sampleRecord.properties.put(propertyRecord.code, value); } } } @@ -320,13 +327,13 @@ public class SampleLister implements ISampleLister TableMap<Long, MetaprojectRecord> metaprojectRecords = new TableMap<Long, MetaprojectRecord>(metaprojects, new IKeyExtractor<Long, MetaprojectRecord>() + { + @Override + public Long getKey(MetaprojectRecord mr) { - @Override - public Long getKey(MetaprojectRecord mr) - { - return mr.id; - } - }); + return mr.id; + } + }); for (EntityMetaprojectRelationRecord record : sampleMetaprojectRelations) { @@ -369,7 +376,8 @@ public class SampleLister implements ISampleLister initializer.setCode(sampleCode); if (sampleRecord.samp_proj_code != null) { - initializer.setIdentifier("/" + spaceCode + "/" + sampleRecord.samp_proj_code + "/" + sampleCode); + initializer.setIdentifier( + "/" + spaceCode + "/" + sampleRecord.samp_proj_code + "/" + sampleCode); } else { initializer.setIdentifier(spaceCode == null ? "/" + sampleCode : "/" + spaceCode + "/" @@ -453,8 +461,10 @@ public class SampleLister implements ISampleLister EnumSet<SampleFetchOption> fetchOptions) { EnumSet<SampleFetchOption> result = - EnumSet.of(fetchOptions.contains(SampleFetchOption.PROPERTIES) ? SampleFetchOption.PROPERTIES - : SampleFetchOption.BASIC); + EnumSet.of(fetchOptions.contains(SampleFetchOption.PROPERTIES) ? + SampleFetchOption.PROPERTIES + : + SampleFetchOption.BASIC); if (fetchOptions.contains(SampleFetchOption.METAPROJECTS)) { result.add(SampleFetchOption.METAPROJECTS); diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/IEntitySearchResult.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/IEntitySearchResult.java index 5907d76a510..eaf7d2054ca 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/IEntitySearchResult.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/IEntitySearchResult.java @@ -15,6 +15,7 @@ */ package ch.systemsx.cisd.openbis.generic.server.business.search.sort; +import java.io.Serializable; import java.util.Map; /** diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java index fbdb7b5cd00..eb8042518c0 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterByScore.java @@ -15,6 +15,7 @@ */ package ch.systemsx.cisd.openbis.generic.server.business.search.sort; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -128,7 +129,7 @@ public class SearchResultSorterByScore implements ISearchResultSorter { for (String propertykey : entity.getProperties().keySet()) { - String propertyValue = entity.getProperties().get(propertykey); + Serializable propertyValue = entity.getProperties().get(propertykey); if (isPartialMatch(propertyValue, partialTerm)) { // If property matches partially score += 100 * boost.getPropertyBoost(propertykey); @@ -234,22 +235,24 @@ public class SearchResultSorterByScore implements ISearchResultSorter return term.replace("*", "").replace("?", ""); } - public boolean isExactMatch(String value, String term) + public boolean isExactMatch(Serializable value, String term) { - if (value != null && term != null) + if (value != null && !value.getClass().isArray() && term != null) { - return value.equalsIgnoreCase(term); + String valueStr = (String) value; + return valueStr.equalsIgnoreCase(term); } else { return false; } } - public boolean isPartialMatch(String value, Pattern pattern) + public boolean isPartialMatch(Serializable value, Pattern pattern) { - if (value != null && pattern != null) + if (value != null && !value.getClass().isArray() && pattern != null) { - return pattern.matcher(value).matches(); + String valueStr = (String) value; + return pattern.matcher(valueStr).matches(); } else { return false; diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetPropertyPE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetPropertyPE.java index e7aee769008..41846f6c8fa 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetPropertyPE.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetPropertyPE.java @@ -39,8 +39,7 @@ import ch.systemsx.cisd.openbis.generic.shared.IServer; * @author Izabela Adamczyk */ @Entity -@Table(name = TableNames.DATA_SET_PROPERTIES_TABLE, uniqueConstraints = @UniqueConstraint(columnNames = -{ ColumnNames.DATA_SET_COLUMN, ColumnNames.DATA_SET_TYPE_PROPERTY_TYPE_COLUMN })) +@Table(name = TableNames.DATA_SET_PROPERTIES_TABLE) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class DataSetPropertyPE extends EntityPropertyWithSampleDataTypePE { diff --git a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePropertyPE.java b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePropertyPE.java index a50820b537f..fbcd69e366e 100644 --- a/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePropertyPE.java +++ b/server-application-server/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePropertyPE.java @@ -39,8 +39,7 @@ import ch.systemsx.cisd.openbis.generic.shared.IServer; * @author Izabela Adamczyk */ @Entity -@Table(name = TableNames.SAMPLE_PROPERTIES_TABLE, uniqueConstraints = { - @UniqueConstraint(columnNames = { ColumnNames.SAMPLE_COLUMN, ColumnNames.SAMPLE_TYPE_PROPERTY_TYPE_COLUMN }) }) +@Table(name = TableNames.SAMPLE_PROPERTIES_TABLE) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class SamplePropertyPE extends EntityPropertyWithSampleDataTypePE { diff --git a/server-application-server/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterTestHelper.java b/server-application-server/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterTestHelper.java index 4f00bd4ab60..adf5deb0cba 100644 --- a/server-application-server/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterTestHelper.java +++ b/server-application-server/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/search/sort/SearchResultSorterTestHelper.java @@ -15,6 +15,7 @@ */ package ch.systemsx.cisd.openbis.generic.server.business.search.sort; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -- GitLab