From 565a09866a98b9087ebe7bdaac41f25121d35619 Mon Sep 17 00:00:00 2001 From: vkovtun <viktor.kovtun@id.ethz.ch> Date: Tue, 7 Feb 2023 12:38:24 +0100 Subject: [PATCH] SSDM-12986 Implemented condition translator for vocabulary property. --- .../v3/search/mapper/CriteriaMapper.java | 5 + ...laryPropertySearchConditionTranslator.java | 116 ++++++++++++++++++ .../asapi/v3/AbstractSearchPropertyTest.java | 89 +++++++++++--- .../search/AbstractEntitySearchCriteria.java | 4 +- ...lledVocabularyPropertySearchCriteria.java} | 13 +- 5 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java rename openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/{VocabularyPropertySearchCriteria.java => ControlledVocabularyPropertySearchCriteria.java} (69%) diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java index c84f5a55155..6b736bd0c90 100644 --- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/mapper/CriteriaMapper.java @@ -70,6 +70,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StrictlyStringProp import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StringFieldSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StringPropertySearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.TextAttributeSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ControlledVocabularyPropertySearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.ArchivingRequestedSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.CompleteSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.search.ContentCopySearchCriteria; @@ -145,6 +146,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.B import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.CodeSearchConditionTranslator; import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.CollectionFieldSearchConditionTranslator; import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.CompleteSearchConditionTranslator; +import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.ControlledVocabularyPropertySearchConditionTranslator; import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.DataSetKindSearchConditionTranslator; import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.DateFieldSearchConditionTranslator; import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.EmailSearchConditionTranslator; @@ -245,6 +247,8 @@ public class CriteriaMapper CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(CodesSearchCriteria.class, collectionFieldSearchConditionTranslator); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(CollectionFieldSearchCriteria.class, collectionFieldSearchConditionTranslator); + CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(ControlledVocabularyPropertySearchCriteria.class, + new ControlledVocabularyPropertySearchConditionTranslator()); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(CompleteSearchCriteria.class, new CompleteSearchConditionTranslator()); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(DataSetKindSearchCriteria.class, new DataSetKindSearchConditionTranslator()); @@ -285,6 +289,7 @@ public class CriteriaMapper booleanFieldSearchConditionTranslator); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(RegistrationDateSearchCriteria.class, dateFieldSearchConditionTranslator); +// CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SamplePropertySearchCriteria.class, ); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(ShareIdSearchCriteria.class, stringFieldSearchConditionTranslator); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SizeSearchCriteria.class, numberFieldSearchConditionTranslator); CRITERIA_TO_CONDITION_TRANSLATOR_MAP.put(SpeedHintSearchCriteria.class, numberFieldSearchConditionTranslator); diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java new file mode 100644 index 00000000000..4bb65920cc9 --- /dev/null +++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/search/translator/condition/ControlledVocabularyPropertySearchConditionTranslator.java @@ -0,0 +1,116 @@ +/* + * Copyright 2011 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition; + +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.AND; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.EQ; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.FROM; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.IN; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.LP; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.PERIOD; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.QU; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.RP; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SELECT; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.SP; +import static ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.SQLLexemes.WHERE; +import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.ID_COLUMN; +import static ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.VOCABULARY_TERM_COLUMN; +import static ch.systemsx.cisd.openbis.generic.shared.dto.TableNames.CONTROLLED_VOCABULARY_TERM_TABLE; + +import java.util.List; +import java.util.Map; + +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractFieldSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ControlledVocabularyPropertySearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchFieldType; +import ch.ethz.sis.openbis.generic.server.asapi.v3.search.mapper.TableMapper; +import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.JoinInformation; +import ch.ethz.sis.openbis.generic.server.asapi.v3.search.translator.condition.utils.TranslatorUtils; + +public class ControlledVocabularyPropertySearchConditionTranslator + implements IConditionTranslator<ControlledVocabularyPropertySearchCriteria> +{ + + @Override + public Map<String, JoinInformation> getJoinInformationMap( + final ControlledVocabularyPropertySearchCriteria criterion, final TableMapper tableMapper, + final IAliasFactory aliasFactory) + { + if (criterion.getFieldType() == SearchFieldType.PROPERTY) + { + return TranslatorUtils.getPropertyJoinInformationMap(tableMapper, aliasFactory); + } else { + throw new IllegalArgumentException(); + } + } + + @Override + public void translate(final ControlledVocabularyPropertySearchCriteria criterion, final TableMapper tableMapper, + final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases, + final Map<String, String> dataTypeByPropertyCode) + { + switch (criterion.getFieldType()) + { + case PROPERTY: + { + doTranslate(criterion, tableMapper, args, sqlBuilder, aliases); + break; + } + + case ANY_FIELD: + case ANY_PROPERTY: + case ATTRIBUTE: + { + throw new IllegalArgumentException("Field type " + criterion.getFieldType() + " is not supported"); + } + } + } + + static void doTranslate(final AbstractFieldSearchCriteria<String> criterion, + final TableMapper tableMapper, + final List<Object> args, final StringBuilder sqlBuilder, final Map<String, JoinInformation> aliases) + { + final String value = criterion.getFieldValue(); + final String valuesTableAlias = aliases.get(tableMapper.getValuesTable()).getSubTableAlias(); + + TranslatorUtils.appendPropertiesExist(sqlBuilder, valuesTableAlias); + sqlBuilder.append(SP).append(AND).append(SP).append(LP); + + appendControlledVocabularyTermIdSubselectConstraint(args, sqlBuilder, value, valuesTableAlias); + + sqlBuilder.append(RP); + } + + private static void appendControlledVocabularyTermIdSubselectConstraint(final List<Object> args, + final StringBuilder sqlBuilder, final String value, final String propertyTableAlias) + { + sqlBuilder.append(propertyTableAlias).append(PERIOD).append(VOCABULARY_TERM_COLUMN) + .append(SP).append(IN).append(SP); + sqlBuilder.append(LP); + + sqlBuilder.append(SELECT).append(SP).append(ID_COLUMN).append(SP) + .append(FROM).append(SP).append(CONTROLLED_VOCABULARY_TERM_TABLE).append(SP) + .append(WHERE).append(SP); + sqlBuilder.append(ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames.CODE_COLUMN); + + sqlBuilder.append(SP).append(EQ).append(SP).append(QU); + args.add(value); + + sqlBuilder.append(RP); + } + +} diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java index 45d3ad7ea38..e0c24b899e7 100644 --- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/AbstractSearchPropertyTest.java @@ -37,6 +37,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.ObjectPermId; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IPermIdHolder; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.AbstractEntitySearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.BooleanFieldSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.ControlledVocabularyPropertySearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.DateFieldSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.NumberFieldSearchCriteria; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.StringFieldSearchCriteria; @@ -857,10 +858,43 @@ public abstract class AbstractSearchPropertyTest extends AbstractTest }; } - @Test(dataProvider = "withControlledVocabularyAsStringPropertyExamples") + @Test(dataProvider = "withControlledVocabularyPropertyExamples") public void testWithControlledVocabularyProperty(final String value, final String queryString, final boolean found) { + // Given + final String sessionToken = v3api.login(TEST_USER, PASSWORD); + + final VocabularyTermCreation vocabularyTermCreation1 = new VocabularyTermCreation(); + vocabularyTermCreation1.setCode("WINTER"); + final VocabularyTermCreation vocabularyTermCreation2 = new VocabularyTermCreation(); + vocabularyTermCreation2.setCode("SPRING"); + final VocabularyTermCreation vocabularyTermCreation3 = new VocabularyTermCreation(); + vocabularyTermCreation3.setCode("SUMMER"); + final VocabularyTermCreation vocabularyTermCreation4 = new VocabularyTermCreation(); + vocabularyTermCreation4.setCode("AUTUMN"); + + final VocabularyCreation vocabularyCreation = new VocabularyCreation(); + vocabularyCreation.setCode("SEASONS"); + vocabularyCreation.setTerms(Arrays.asList(vocabularyTermCreation1, vocabularyTermCreation2, + vocabularyTermCreation3, vocabularyTermCreation4)); + final VocabularyPermId vocabularyPermId = + v3api.createVocabularies(sessionToken, Collections.singletonList(vocabularyCreation)).get(0); + + final PropertyTypePermId propertyTypeId = createAPropertyType(sessionToken, DataType.CONTROLLEDVOCABULARY, + vocabularyPermId); + final ObjectPermId entityPermId = createEntity(sessionToken, propertyTypeId, value); + final AbstractEntitySearchCriteria<?> searchCriteria = createSearchCriteria(); + new VocabularyQueryInjector(searchCriteria, propertyTypeId).buildCriteria(queryString); + // When + final List<? extends IPermIdHolder> entities = search(sessionToken, searchCriteria); + + // Then + assertEquals(entities.size(), found ? 1 : 0); + if (found) + { + assertEquals(entities.get(0).getPermId().toString(), entityPermId.getPermId()); + } } @Test @@ -879,21 +913,21 @@ public abstract class AbstractSearchPropertyTest extends AbstractTest assertEquals(entities.size(), 1); } -// @Test -// public void testSearchWithSampleProperty() -// { -// final String sessionToken = v3api.login(TEST_USER, PASSWORD); -// final PropertyTypePermId propertyTypeId = createASamplePropertyType(sessionToken, null); -// -// createEntity(sessionToken, propertyTypeId, "/CISD/CL1"); -// -// final AbstractEntitySearchCriteria<?> searchCriteria = createSearchCriteria(); -// searchCriteria.withOrOperator(); -// searchCriteria.withSampleProperty(propertyTypeId.getPermId()).thatEquals("/CISD/CL1"); -// -// final List<? extends IPermIdHolder> entities = search(sessionToken, searchCriteria); -// assertEquals(entities.size(), 1); -// } + @Test(enabled = false) + public void testSearchWithSampleProperty() + { + final String sessionToken = v3api.login(TEST_USER, PASSWORD); + final PropertyTypePermId propertyTypeId = createASamplePropertyType(sessionToken, null); + + createEntity(sessionToken, propertyTypeId, "/CISD/CL1"); + + final AbstractEntitySearchCriteria<?> searchCriteria = createSearchCriteria(); + searchCriteria.withOrOperator(); + searchCriteria.withSampleProperty(propertyTypeId.getPermId()).thatEquals("/CISD/CL1"); + + final List<? extends IPermIdHolder> entities = search(sessionToken, searchCriteria); + assertEquals(entities.size(), 1); + } @Test public void testSearchWithPropertyMatchingMaterialProperty() @@ -1477,4 +1511,27 @@ public abstract class AbstractSearchPropertyTest extends AbstractTest } } } + + static final class VocabularyQueryInjector extends AbstractQueryInjector + { + VocabularyQueryInjector(final AbstractEntitySearchCriteria<?> searchCriteria, + final PropertyTypePermId propertyTypeId) + { + super(searchCriteria, propertyTypeId); + } + + @Override + protected void injectQuery(final Operator operator, final String operand) + { + final ControlledVocabularyPropertySearchCriteria criteria = + searchCriteria.withVocabularyProperty(propertyTypeId.getPermId()); + if (operator == Operator.EQUAL) + { + criteria.thatEquals(operand); + } else + { + throw new IllegalArgumentException("Unsupported operator " + operator); + } + } + } } diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/AbstractEntitySearchCriteria.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/AbstractEntitySearchCriteria.java index 573d390a538..abfea0bf12d 100644 --- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/AbstractEntitySearchCriteria.java +++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/AbstractEntitySearchCriteria.java @@ -116,9 +116,9 @@ public abstract class AbstractEntitySearchCriteria<ID extends IObjectId> extends return with(new SamplePropertySearchCriteria(propertyName)); } - public VocabularyPropertySearchCriteria withVocabularyProperty(final String propertyName) + public ControlledVocabularyPropertySearchCriteria withVocabularyProperty(final String propertyName) { - return with(new VocabularyPropertySearchCriteria(propertyName)); + return with(new ControlledVocabularyPropertySearchCriteria(propertyName)); } /** diff --git a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/VocabularyPropertySearchCriteria.java b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/ControlledVocabularyPropertySearchCriteria.java similarity index 69% rename from openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/VocabularyPropertySearchCriteria.java rename to openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/ControlledVocabularyPropertySearchCriteria.java index 0d64f8123b9..2b6a8495ae1 100644 --- a/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/VocabularyPropertySearchCriteria.java +++ b/openbis_api/source/java/ch/ethz/sis/openbis/generic/asapi/v3/dto/common/search/ControlledVocabularyPropertySearchCriteria.java @@ -18,16 +18,21 @@ package ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search; import ch.systemsx.cisd.base.annotation.JsonObject; -// TODO: add JS criteria -@JsonObject("as.dto.common.search.VocabularyPropertySearchCriteria") -public class VocabularyPropertySearchCriteria extends AbstractFieldSearchCriteria<String> +// TODO: add JS criteria! +@JsonObject("as.dto.common.search.ControlledVocabularyPropertySearchCriteria") +public class ControlledVocabularyPropertySearchCriteria extends AbstractFieldSearchCriteria<String> { private static final long serialVersionUID = 1L; - VocabularyPropertySearchCriteria(final String propertyName) + ControlledVocabularyPropertySearchCriteria(final String propertyName) { super(propertyName, SearchFieldType.PROPERTY); } + public void thatEquals(final String value) + { + setFieldValue(value); + } + } -- GitLab