Skip to content

Commit b479218

Browse files
authored
Merge pull request #108 from evgeniycheban/gh-107
Consider supporting Enum type for index
2 parents b790ad6 + 91cf29e commit b479218

6 files changed

Lines changed: 193 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2020 Restream
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package ru.rt.restream.reindexer;
17+
18+
/**
19+
* Reindexer enum item field mapping type.
20+
*/
21+
public enum EnumType {
22+
23+
/**
24+
* Persist enumerated type property or field as an integer.
25+
*/
26+
ORDINAL,
27+
28+
/**
29+
* Persist enumerated type property or field as a string.
30+
*/
31+
STRING
32+
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2020 Restream
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package ru.rt.restream.reindexer.annotations;
17+
18+
import ru.rt.restream.reindexer.EnumType;
19+
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
25+
/**
26+
* Specifies the mapping for an enum item field.
27+
* Provides support to persist an enum as a String or Integer using {@link EnumType}.
28+
*/
29+
@Target(ElementType.FIELD)
30+
@Retention(RetentionPolicy.RUNTIME)
31+
public @interface Enumerated {
32+
33+
/**
34+
* (Optional) The type used in mapping an enum type.
35+
*
36+
* @return The type used in mapping an enum type
37+
*/
38+
EnumType value() default EnumType.ORDINAL;
39+
40+
}

src/main/java/ru/rt/restream/reindexer/annotations/ReindexAnnotationScanner.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package ru.rt.restream.reindexer.annotations;
1717

1818
import ru.rt.restream.reindexer.CollateMode;
19+
import ru.rt.restream.reindexer.EnumType;
1920
import ru.rt.restream.reindexer.FieldType;
2021
import ru.rt.restream.reindexer.IndexType;
2122
import ru.rt.restream.reindexer.ReindexScanner;
@@ -259,6 +260,9 @@ private FieldInfo getFieldInfo(Field field) {
259260
fieldType = getFieldTypeByClass(componentType);
260261
fieldInfo.componentType = componentType;
261262
}
263+
} else if (Enum.class.isAssignableFrom(type)) {
264+
Enumerated enumerated = field.getAnnotation(Enumerated.class);
265+
fieldType = enumerated != null && enumerated.value() == EnumType.STRING ? STRING : INT;
262266
} else {
263267
fieldType = getFieldTypeByClass(type);
264268
}

src/main/java/ru/rt/restream/reindexer/binding/cproto/cjson/CJsonItemWriter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package ru.rt.restream.reindexer.binding.cproto.cjson;
1717

18+
import ru.rt.restream.reindexer.EnumType;
19+
import ru.rt.restream.reindexer.annotations.Enumerated;
1820
import ru.rt.restream.reindexer.annotations.Json;
1921
import ru.rt.restream.reindexer.annotations.Reindex;
2022
import ru.rt.restream.reindexer.annotations.Transient;
@@ -90,6 +92,14 @@ private CjsonElement toCjson(Object source) {
9092
if (field.getType() == String.class && field.isAnnotationPresent(Reindex.class)
9193
&& field.getAnnotation(Reindex.class).isUuid()) {
9294
cjsonElement = new CjsonPrimitive(UUID.fromString((String) fieldValue));
95+
} else if (Enum.class.isAssignableFrom(field.getType())) {
96+
Enumerated enumerated = field.getAnnotation(Enumerated.class);
97+
if (enumerated != null && enumerated.value() == EnumType.STRING) {
98+
cjsonElement = new CjsonPrimitive(((Enum<?>) fieldValue).name());
99+
} else {
100+
int ordinal = ((Enum<?>) fieldValue).ordinal();
101+
cjsonElement = new CjsonPrimitive((long) ordinal);
102+
}
93103
} else {
94104
cjsonElement = toCjson(fieldValue);
95105
}

src/main/java/ru/rt/restream/reindexer/binding/cproto/cjson/CjsonItemReader.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package ru.rt.restream.reindexer.binding.cproto.cjson;
1717

18+
import ru.rt.restream.reindexer.EnumType;
19+
import ru.rt.restream.reindexer.annotations.Enumerated;
1820
import ru.rt.restream.reindexer.annotations.Json;
1921
import ru.rt.restream.reindexer.binding.cproto.ByteBuffer;
2022
import ru.rt.restream.reindexer.binding.cproto.ItemReader;
@@ -85,6 +87,12 @@ private Object getTargetValue(Field field, CjsonElement property) {
8587
elements.add(convert(cjsonElement, (Class<?>) elementType));
8688
}
8789
return elements;
90+
} else if (Enum.class.isAssignableFrom(fieldType)) {
91+
Enumerated enumerated = field.getAnnotation(Enumerated.class);
92+
if (enumerated != null && enumerated.value() == EnumType.STRING) {
93+
return Enum.valueOf(fieldType.asSubclass(Enum.class), property.getAsString());
94+
}
95+
return fieldType.getEnumConstants()[property.getAsInteger()];
8896
} else {
8997
return convert(property, field.getType());
9098
}

src/test/java/ru/rt/restream/reindexer/connector/ReindexerTest.java

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@
2222
import lombok.NoArgsConstructor;
2323
import lombok.Setter;
2424
import org.junit.jupiter.api.Test;
25+
import ru.rt.restream.reindexer.EnumType;
2526
import ru.rt.restream.reindexer.Namespace;
2627
import ru.rt.restream.reindexer.NamespaceOptions;
2728
import ru.rt.restream.reindexer.QueryResultJsonIterator;
2829
import ru.rt.restream.reindexer.ResultIterator;
2930
import ru.rt.restream.reindexer.Transaction;
31+
import ru.rt.restream.reindexer.annotations.Enumerated;
3032
import ru.rt.restream.reindexer.annotations.Reindex;
3133
import ru.rt.restream.reindexer.annotations.Serial;
3234
import ru.rt.restream.reindexer.db.DbBaseTest;
@@ -2774,6 +2776,51 @@ public void testIsAppendableIndexItem() {
27742776
assertThat(iterator.hasNext(), is(false));
27752777
}
27762778

2779+
@Test
2780+
public void testTestItemEnumString() {
2781+
String namespaceName = "items";
2782+
db.openNamespace(namespaceName, NamespaceOptions.defaultOptions(), TestItemEnumString.class);
2783+
db.upsert(namespaceName, new TestItemEnumString(1, "TestName", TestEnum.TEST_CONSTANT));
2784+
Iterator<TestItemEnumString> iterator = db.query(namespaceName, TestItemEnumString.class)
2785+
.where("testEnumString", EQ, TestEnum.TEST_CONSTANT.name())
2786+
.execute();
2787+
assertThat(iterator.hasNext(), is(true));
2788+
TestItemEnumString foundByEnumString = iterator.next();
2789+
assertThat(foundByEnumString.id, is(1));
2790+
assertThat(foundByEnumString.name, is("TestName"));
2791+
assertThat(foundByEnumString.testEnum, is(TestEnum.TEST_CONSTANT));
2792+
}
2793+
2794+
@Test
2795+
public void testTestItemEnumOrdinal() {
2796+
String namespaceName = "items";
2797+
db.openNamespace(namespaceName, NamespaceOptions.defaultOptions(), TestItemEnumOrdinal.class);
2798+
db.upsert(namespaceName, new TestItemEnumOrdinal(1, "TestName", TestEnum.TEST_CONSTANT));
2799+
Iterator<TestItemEnumOrdinal> iterator = db.query(namespaceName, TestItemEnumOrdinal.class)
2800+
.where("testEnum", EQ, TestEnum.TEST_CONSTANT.ordinal())
2801+
.execute();
2802+
assertThat(iterator.hasNext(), is(true));
2803+
TestItemEnumOrdinal foundByEnumOrdinal = iterator.next();
2804+
assertThat(foundByEnumOrdinal.id, is(1));
2805+
assertThat(foundByEnumOrdinal.name, is("TestName"));
2806+
assertThat(foundByEnumOrdinal.testEnum, is(TestEnum.TEST_CONSTANT));
2807+
}
2808+
2809+
@Test
2810+
public void testTestItemEnumDefault() {
2811+
String namespaceName = "items";
2812+
db.openNamespace(namespaceName, NamespaceOptions.defaultOptions(), TestItemEnumDefault.class);
2813+
db.upsert(namespaceName, new TestItemEnumDefault(1, "TestName", TestEnum.TEST_CONSTANT));
2814+
Iterator<TestItemEnumDefault> iterator = db.query(namespaceName, TestItemEnumDefault.class)
2815+
.where("testEnum", EQ, TestEnum.TEST_CONSTANT.ordinal())
2816+
.execute();
2817+
assertThat(iterator.hasNext(), is(true));
2818+
TestItemEnumDefault foundByEnumOrdinal = iterator.next();
2819+
assertThat(foundByEnumOrdinal.id, is(1));
2820+
assertThat(foundByEnumOrdinal.name, is("TestName"));
2821+
assertThat(foundByEnumOrdinal.testEnum, is(TestEnum.TEST_CONSTANT));
2822+
}
2823+
27772824
@Getter
27782825
@Setter
27792826
public static class SerialIdTestItem {
@@ -2877,4 +2924,55 @@ public static class ItemWithAppendableIndexes {
28772924
@Reindex(name = "name", isAppendable = true, type = TEXT)
28782925
private String description;
28792926
}
2927+
2928+
@Getter
2929+
@Setter
2930+
@NoArgsConstructor
2931+
@AllArgsConstructor
2932+
public static class TestItemEnumString {
2933+
@Reindex(name = "id", isPrimaryKey = true)
2934+
private Integer id;
2935+
2936+
@Reindex(name = "name")
2937+
private String name;
2938+
2939+
@Enumerated(EnumType.STRING)
2940+
@Reindex(name = "testEnumString")
2941+
private TestEnum testEnum;
2942+
}
2943+
2944+
@Getter
2945+
@Setter
2946+
@NoArgsConstructor
2947+
@AllArgsConstructor
2948+
public static class TestItemEnumOrdinal {
2949+
@Reindex(name = "id", isPrimaryKey = true)
2950+
private Integer id;
2951+
2952+
@Reindex(name = "name")
2953+
private String name;
2954+
2955+
@Enumerated(EnumType.ORDINAL)
2956+
@Reindex(name = "testEnumOrdinal")
2957+
private TestEnum testEnum;
2958+
}
2959+
2960+
@Getter
2961+
@Setter
2962+
@NoArgsConstructor
2963+
@AllArgsConstructor
2964+
public static class TestItemEnumDefault {
2965+
@Reindex(name = "id", isPrimaryKey = true)
2966+
private Integer id;
2967+
2968+
@Reindex(name = "name")
2969+
private String name;
2970+
2971+
@Reindex(name = "testEnum")
2972+
private TestEnum testEnum;
2973+
}
2974+
2975+
public enum TestEnum {
2976+
TEST_CONSTANT
2977+
}
28802978
}

0 commit comments

Comments
 (0)