Skip to content

Commit 3f412df

Browse files
committed
GenericUtils.getParameterType
1 parent 8e0c2a5 commit 3f412df

File tree

3 files changed

+98
-5
lines changed

3 files changed

+98
-5
lines changed

src/main/java/net/elytrium/serializer/language/reader/AbstractReader.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import net.elytrium.serializer.custom.ClassSerializer;
3737
import net.elytrium.serializer.exceptions.ReflectionException;
3838
import net.elytrium.serializer.exceptions.SerializableReadException;
39+
import net.elytrium.serializer.utils.GenericUtils;
3940

4041
public abstract class AbstractReader {
4142

@@ -195,9 +196,11 @@ public Object readByType(@Nullable Field owner, @Nullable Object holder, Type ty
195196
return this.readGuessingType(owner);
196197
} else if (type instanceof ParameterizedType parameterizedType) {
197198
Class<?> clazz = (Class<?>) parameterizedType.getRawType();
198-
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
199-
return Map.class.isAssignableFrom(clazz) ? this.readMap(owner, actualTypeArguments[0], actualTypeArguments[1])
200-
: List.class.isAssignableFrom(clazz) ? this.readList(owner, actualTypeArguments[0])
199+
return Map.class.isAssignableFrom(clazz) ? this.readMap(owner,
200+
GenericUtils.getParameterType(Map.class, parameterizedType, 0),
201+
GenericUtils.getParameterType(Map.class, parameterizedType, 1))
202+
: List.class.isAssignableFrom(clazz) ? this.readList(owner,
203+
GenericUtils.getParameterType(List.class, parameterizedType, 0))
201204
: this.readGuessingType(owner);
202205
} else if (type instanceof Class<?> clazz) {
203206
if (Map.class.isAssignableFrom(clazz)) {

src/main/java/net/elytrium/serializer/language/reader/YamlReader.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import net.elytrium.serializer.placeholders.DefaultPlaceholderReplacer;
4646
import net.elytrium.serializer.placeholders.PlaceholderReplacer;
4747
import net.elytrium.serializer.placeholders.Placeholders;
48+
import net.elytrium.serializer.utils.GenericUtils;
4849

4950
@SuppressWarnings({"SizeReplaceableByIsEmpty", "StringRepeatCanBeUsed"}) // Ignore modern methods, because we support up to Java 8.
5051
public class YamlReader extends AbstractReader {
@@ -188,15 +189,20 @@ private void updatePlaceholders(Object holder, Field node) throws ReflectiveOper
188189

189190
if (placeholders != null) {
190191
PlaceholderReplacer<?, ?> replacer = null;
192+
Object value = node.get(holder);
191193
if (placeholders.replacer() == DefaultPlaceholderReplacer.class) {
192-
replacer = this.config.getRegisteredReplacer(node.getType());
194+
if (value instanceof Collection<?>) {
195+
replacer = this.config.getRegisteredReplacer(
196+
(Class<?>) GenericUtils.getParameterType(Collection.class, node.getGenericType(), 0));
197+
} else {
198+
replacer = this.config.getRegisteredReplacer(node.getType());
199+
}
193200
}
194201

195202
if (replacer == null) {
196203
replacer = this.config.getAndCacheReplacer(placeholders.replacer());
197204
}
198205

199-
Object value = node.get(holder);
200206
if (this.config.isRegisterPlaceholdersForCollectionEntries() && value instanceof Collection<?> collection) {
201207
for (Object entry : collection) {
202208
Placeholders.addPlaceholders(entry, replacer, placeholders.wrapWithBraces(), placeholders.value());
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (C) 2023 Elytrium
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Lesser General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package net.elytrium.serializer.utils;
19+
20+
import java.lang.reflect.ParameterizedType;
21+
import java.lang.reflect.Type;
22+
import java.lang.reflect.TypeVariable;
23+
24+
public class GenericUtils {
25+
26+
public static int getParameterIndex(TypeVariable<?>[] variables, TypeVariable<?> expected) {
27+
for (int i = 0; i < variables.length; ++i) {
28+
if (variables[i].getName().equals(expected.getName())) {
29+
return i;
30+
}
31+
}
32+
33+
return -1;
34+
}
35+
36+
public static Type getParameterTypeFromSuperclass(Class<?> parent, Type type, Type superclass, int searchIndex) {
37+
Type superclassType = GenericUtils.getParameterType(parent, superclass, searchIndex);
38+
if (superclassType instanceof TypeVariable<?> typeVariable && type instanceof ParameterizedType parameterizedType) {
39+
Class<?> rawSuperclass = (Class<?>) parameterizedType.getRawType();
40+
int index = GenericUtils.getParameterIndex(rawSuperclass.getTypeParameters(), typeVariable);
41+
if (index != -1) {
42+
return parameterizedType.getActualTypeArguments()[index];
43+
}
44+
}
45+
46+
return superclassType;
47+
}
48+
49+
public static Type getParameterType(Class<?> parent, Type type, int index) {
50+
if (type == null) {
51+
return null;
52+
}
53+
54+
Class<?> clazz = null;
55+
56+
if (type instanceof ParameterizedType parameterizedType) {
57+
clazz = (Class<?>) parameterizedType.getRawType();
58+
if (clazz.equals(parent)) {
59+
return parameterizedType.getActualTypeArguments()[index];
60+
}
61+
}
62+
63+
if (type instanceof Class<?> typeClazz) {
64+
clazz = typeClazz;
65+
}
66+
67+
if (clazz != null) {
68+
Type genericSuperclass = clazz.getGenericSuperclass();
69+
Type superclassType = GenericUtils.getParameterTypeFromSuperclass(parent, type, genericSuperclass, index);
70+
if (superclassType != null) {
71+
return superclassType;
72+
}
73+
74+
for (Type genericInterface : clazz.getGenericInterfaces()) {
75+
Type genericInterfaceType = GenericUtils.getParameterTypeFromSuperclass(parent, type, genericInterface, index);
76+
if (genericInterfaceType != null) {
77+
return genericInterfaceType;
78+
}
79+
}
80+
}
81+
82+
return null;
83+
}
84+
}

0 commit comments

Comments
 (0)