From ea7964d2244b197933455dcf42e3460433877c0d Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 1 Sep 2021 15:40:38 +0200 Subject: [PATCH] Add support for enum fields during indexing (#1792) * Add support for enum fields during indexing * Add missing value extractor for enums --- gradle/changelog/enum_fields.yaml | 2 + .../sonia/scm/search/IndexableFields.java | 21 ++++++++ .../sonia/scm/search/ValueExtractors.java | 7 +++ .../sonia/scm/search/TypeConvertersTest.java | 22 ++++++++ .../sonia/scm/search/ValueExtractorsTest.java | 50 +++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 gradle/changelog/enum_fields.yaml create mode 100644 scm-webapp/src/test/java/sonia/scm/search/ValueExtractorsTest.java diff --git a/gradle/changelog/enum_fields.yaml b/gradle/changelog/enum_fields.yaml new file mode 100644 index 0000000000..354d7dcb63 --- /dev/null +++ b/gradle/changelog/enum_fields.yaml @@ -0,0 +1,2 @@ +- type: added + description: Support for enum fields during indexing ([#1792](https://github.com/scm-manager/scm-manager/pull/1792)) diff --git a/scm-webapp/src/main/java/sonia/scm/search/IndexableFields.java b/scm-webapp/src/main/java/sonia/scm/search/IndexableFields.java index cd662edb35..c0490b9034 100644 --- a/scm-webapp/src/main/java/sonia/scm/search/IndexableFields.java +++ b/scm-webapp/src/main/java/sonia/scm/search/IndexableFields.java @@ -73,6 +73,8 @@ class IndexableFields { return new BooleanFieldFactory(indexType); } else if (isInstant(fieldType)) { return new InstantFieldFactory(indexType); + } else if (fieldType.isEnum()) { + return new EnumFieldFactory(indexType); } else { throw new UnsupportedTypeOfFieldException(fieldType, field.getName()); } @@ -169,4 +171,23 @@ class IndexableFields { } } + private static class EnumFieldFactory implements IndexableFieldFactory { + + private final Indexed.Type type; + + public EnumFieldFactory(Indexed.Type type) { + this.type = type; + } + + @Override + public Iterable create(String name, Object value) { + String stringValue = value.toString(); + if (type.isSearchable()) { + return singleton(new StringField(name, stringValue, Store.YES)); + } else { + return singleton(new StoredField(name, stringValue)); + } + } + } + } diff --git a/scm-webapp/src/main/java/sonia/scm/search/ValueExtractors.java b/scm-webapp/src/main/java/sonia/scm/search/ValueExtractors.java index d002aac246..82c8538061 100644 --- a/scm-webapp/src/main/java/sonia/scm/search/ValueExtractors.java +++ b/scm-webapp/src/main/java/sonia/scm/search/ValueExtractors.java @@ -45,11 +45,18 @@ final class ValueExtractors { return booleanExtractor(name); } else if (TypeCheck.isInstant(type)) { return instantExtractor(name); + } else if (type.isEnum()) { + return enumExtractor(name, type); } else { throw new UnsupportedTypeOfFieldException(type, name); } } + @SuppressWarnings({"unchecked", "rawtypes"}) + private static ValueExtractor enumExtractor(String name, Class type) { + return doc -> Enum.valueOf(type, doc.get(name)); + } + @Nonnull private static ValueExtractor stringExtractor(String name) { return doc -> doc.get(name); diff --git a/scm-webapp/src/test/java/sonia/scm/search/TypeConvertersTest.java b/scm-webapp/src/test/java/sonia/scm/search/TypeConvertersTest.java index 33d7c0b7e7..98a9c9e8c7 100644 --- a/scm-webapp/src/test/java/sonia/scm/search/TypeConvertersTest.java +++ b/scm-webapp/src/test/java/sonia/scm/search/TypeConvertersTest.java @@ -200,6 +200,13 @@ class TypeConvertersTest { assertThat(document.getField("lastName")).isNull(); } + @Test + void shouldCreateEnumField() { + Document document = convert(new TypeWithEnum(Color.GREEN)); + + assertThat(document.get("color")).isEqualTo("GREEN"); + } + private void assertPointField(Document document, String name, Consumer consumer) { IndexableField[] fields = document.getFields(name); assertThat(fields) @@ -291,4 +298,19 @@ class TypeConvertersTest { this.storedOnlyInstant = instant; } } + + @Getter + @IndexedType + private static class TypeWithEnum { + @Indexed + private final Color color; + + private TypeWithEnum(Color color) { + this.color = color; + } + } + + private enum Color { + GREEN, RED, BLUE, YELLOW + } } diff --git a/scm-webapp/src/test/java/sonia/scm/search/ValueExtractorsTest.java b/scm-webapp/src/test/java/sonia/scm/search/ValueExtractorsTest.java new file mode 100644 index 0000000000..446148b0c5 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/search/ValueExtractorsTest.java @@ -0,0 +1,50 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.search; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.StoredField; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ValueExtractorsTest { + + @Test + void shouldExtractEnumValue() { + Document document = new Document(); + document.add(new StoredField("animal", "PENGUIN")); + + ValueExtractor extractor = ValueExtractors.create("animal", Animal.class); + Object value = extractor.extract(document); + + assertThat(value).isEqualTo(Animal.PENGUIN); + } + + enum Animal { + PENGUIN, ALPACA + } + +}