Skip to content

Commit 5c42567

Browse files
committed
Merge branch 'refs/heads/feat-gui' into dev
# Conflicts: # common/base/src/main/java/it/angrybear/yagl/utils/ObjectUtils.java # item/bukkit/src/test/java/it/angrybear/yagl/listeners/PersistentListenerTest.java
2 parents e45408b + 2dc48a0 commit 5c42567

File tree

119 files changed

+7190
-1465
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+7190
-1465
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
Its core functions relate to the [Bukkit project](https://dev.bukkit.org/), but one can use the **base** modules across any preferred platform.
44

5-
Since every module provides a **serializer** one, to load and save the objects, it is possible to store or create **GUIs** and **custom Items** in unrelated platforms;
5+
Since every module provides a **serializer** one to load and save the objects,
6+
it is possible to store or create **GUIs** and **custom Items** in unrelated platforms;
67
then, send the actual data to a [Bukkit](https://dev.bukkit.org/) backend and display it.
78

89
For example, a `/hub` plugin that works with [BungeeCord](https://www.spigotmc.org/wiki/bungeecord/) or [Velocity](https://papermc.io/software/velocity).

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ allprojects {
112112
}
113113

114114
if (!projectName.contains("-"))
115-
subprojects.findAll { !it.name.equals(TEST_MODULE) } .each {api project(it.path)}
115+
subprojects.findAll { (it.name != TEST_MODULE) } .each {api project(it.path)}
116116

117117
testCompileOnly libs.lombok
118118
testAnnotationProcessor libs.lombok

common/base/src/main/java/it/angrybear/yagl/utils/ObjectUtils.java

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,102 @@
33
import it.fulminazzo.fulmicollection.objects.Refl;
44
import it.fulminazzo.fulmicollection.structures.Tuple;
55
import it.fulminazzo.fulmicollection.utils.ReflectionUtils;
6+
import lombok.AccessLevel;
7+
import lombok.NoArgsConstructor;
8+
import org.jetbrains.annotations.NotNull;
69
import org.jetbrains.annotations.Nullable;
710

8-
import java.lang.reflect.Field;
9-
import java.util.Collection;
10-
import java.util.LinkedHashMap;
11-
import java.util.Map;
11+
import java.lang.reflect.*;
12+
import java.util.*;
1213
import java.util.stream.Collectors;
1314

1415
/**
1516
* The type Object utils.
1617
*/
17-
public class ObjectUtils {
18+
@SuppressWarnings("unchecked")
19+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
20+
public final class ObjectUtils {
1821
private static final String EMPTY_IDENTIFIER = "";
1922

23+
/**
24+
* Copies the given object to a new one.
25+
*
26+
* @param <T> the type of the object to copy from
27+
* @param t the object to copy from
28+
* @return the copy
29+
*/
30+
public static <T> T copy(final @NotNull T t) {
31+
Class<? extends T> clazz = (Class<? extends T>) t.getClass();
32+
try {
33+
ReflectionUtils.getConstructor(clazz);
34+
} catch (Exception e) {
35+
// Get the most abstract class
36+
Class<?> c = clazz;
37+
Class<?>[] interfaces;
38+
while ((interfaces = c.getInterfaces()).length != 0) {
39+
Class<?> tmp = interfaces[0];
40+
if (!tmp.equals(Iterable.class) && !tmp.getSimpleName().startsWith("Abstract"))
41+
c = tmp;
42+
else break;
43+
}
44+
clazz = ReflectionUtils.getClass(c.getCanonicalName() + "Impl");
45+
}
46+
return copy(t, clazz);
47+
}
48+
49+
/**
50+
* Copies the given object to a new one using the provided class.
51+
* If an interface is provided, it tries to convert it to a non-abstract implementation by appending <i>Impl</i>.
52+
* If no such class is found, an {@link IllegalArgumentException} is thrown.
53+
*
54+
* @param <T> the type of the object to copy from
55+
* @param <O> the type of the returned object
56+
* @param t the object to copy from
57+
* @param clazz the class to copy to
58+
* @return the copy
59+
*/
60+
public static <T, O extends T> O copy(final @NotNull T t, @NotNull Class<O> clazz) {
61+
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()))
62+
try {
63+
clazz = ReflectionUtils.getClass(clazz.getCanonicalName() + "Impl");
64+
} catch (IllegalArgumentException e) {
65+
throw new IllegalArgumentException(String.format("Could not copy object to abstract class '%s': no '%sImpl' class found",
66+
clazz.getCanonicalName(), clazz.getCanonicalName()));
67+
}
68+
69+
Refl<O> object = new Refl<>(clazz, new Object[0]);
70+
for (final Field field : object.getNonStaticFields())
71+
try {
72+
Object obj1 = ReflectionUtils.get(field, t);
73+
if (obj1 instanceof Collection) {
74+
Class<?> tmpClass = obj1.getClass();
75+
// In the case of creation with Arrays.asList()
76+
if (tmpClass.getCanonicalName().equals(Arrays.class.getCanonicalName() + ".ArrayList"))
77+
tmpClass = ArrayList.class;
78+
Class<Collection<Object>> finalClass = (Class<Collection<Object>>) tmpClass;
79+
obj1 = ((Collection<?>) obj1).stream()
80+
.collect(Collectors.toCollection(() -> new Refl<>(finalClass, new Object[0]).getObject()));
81+
} else if (obj1 instanceof Map) {
82+
Map<Object, Object> map = new HashMap<>();
83+
((Map<Object, Object>) obj1).putAll(map);
84+
obj1 = map;
85+
} else if (obj1 != null)
86+
if (obj1.getClass().isArray()) {
87+
Object[] tmp = (Object[]) obj1;
88+
Object[] arr = (Object[]) Array.newInstance(obj1.getClass().getComponentType(), tmp.length);
89+
System.arraycopy(tmp, 0, arr, 0, arr.length);
90+
obj1 = arr;
91+
} else
92+
try {
93+
Method copy = obj1.getClass().getDeclaredMethod("copy");
94+
obj1 = ReflectionUtils.setAccessible(copy).invoke(obj1);
95+
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ignored) {}
96+
object.setFieldObject(field, obj1);
97+
} catch (IllegalArgumentException ignored) {}
98+
99+
return object.getObject();
100+
}
101+
20102
/**
21103
* Prints the given object in a JSON format.
22104
* If the object (or an object contained in it) is "empty",
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package it.angrybear.yagl.utils;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.util.Arrays;
7+
import java.util.Iterator;
8+
import java.util.List;
9+
10+
import static org.junit.jupiter.api.Assertions.*;
11+
12+
class ObjectUtilsTest {
13+
14+
@Test
15+
void testCopyOfNoInterface() {
16+
Object current = new CopyNoInterface("hello");
17+
Object o = ObjectUtils.copy(current);
18+
assertInstanceOf(CopyNoInterfaceImpl.class, o);
19+
assertNotEquals(current, o);
20+
}
21+
22+
@Test
23+
void testCopyOfIterable() {
24+
Object current = new CopyIterable("hello");
25+
Object o = ObjectUtils.copy(current);
26+
assertInstanceOf(CopyIterableImpl.class, o);
27+
assertNotEquals(current, o);
28+
}
29+
30+
@Test
31+
void testCopyOfData() {
32+
GeneralCopy c1 = new GeneralCopy();
33+
GeneralCopy c2 = ObjectUtils.copy(c1);
34+
assertNotEquals(c1.list.getClass(), c2.list.getClass());
35+
assertIterableEquals(c1.list, c2.list);
36+
assertNotEquals(c1.array, c2.array);
37+
assertArrayEquals(c1.array, c2.array);
38+
assertNotEquals(c1.copiable, c2.copiable);
39+
}
40+
41+
private static class GeneralCopy {
42+
List<String> list = Arrays.asList("hello", "world");
43+
String[] array = new String[]{"hello", "world"};
44+
GeneralCopiable copiable = new GeneralCopiable();
45+
}
46+
47+
private static class GeneralCopiable {
48+
49+
public GeneralCopiable copy() {
50+
return new GeneralCopiable();
51+
}
52+
}
53+
54+
private static class CopyIterableImpl { }
55+
56+
private static class CopyIterable implements Iterable<String> {
57+
58+
public CopyIterable(String s) {
59+
60+
}
61+
62+
@NotNull
63+
@Override
64+
public Iterator<String> iterator() {
65+
return null;
66+
}
67+
}
68+
69+
private static class CopyNoInterfaceImpl { }
70+
71+
private static class CopyNoInterface {
72+
73+
public CopyNoInterface(String s) {
74+
75+
}
76+
}
77+
}

common/serializer/src/main/java/it/angrybear/yagl/parsers/TypedParser.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
import it.fulminazzo.yamlparser.configuration.IConfiguration;
77
import it.fulminazzo.yamlparser.parsers.CallableYAMLParser;
88
import org.jetbrains.annotations.NotNull;
9-
import org.jetbrains.annotations.Nullable;
109

1110
/**
12-
* This parser allows to parse an object using the {@link CallableYAMLParser} methods.
11+
* This parser allows parsing an object using the {@link CallableYAMLParser} methods.
1312
* However, it forces the saved object to store a <i>type</i> field, that contains the name of the class of the original object.
1413
* Upon loading, this class is retrieved (and will throw errors for invalid values) to recreate the object.
1514
*
@@ -34,7 +33,7 @@ public TypedParser(final @NotNull Class<C> clazz) {
3433

3534
@SuppressWarnings("unchecked")
3635
@Override
37-
protected @NotNull TriConsumer<@NotNull IConfiguration, @NotNull String, @Nullable C> getDumper() {
36+
protected TriConsumer<IConfiguration, String, C> getDumper() {
3837
return (c, s, g) -> {
3938
super.getDumper().accept(c, s, g);
4039
if (g == null) return;

common/serializer/src/main/java/it/angrybear/yagl/parsers/YAGLParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public final class YAGLParser {
1212

1313
/**
1414
* Adds all the parsers from the {@link it.angrybear.yagl.parsers} package to {@link FileConfiguration}.
15-
* @deprecated This will NOT add module specific parsers. It is recommended to look for the <b>&lt;module&gt;YAGLParser</b> class instead.
15+
* @deprecated This will NOT add module-specific parsers. It is recommended to look for the <b>&lt;module&gt;YAGLParser</b> class instead.
1616
*/
1717
@Deprecated
1818
public static void addAllParsers() {

common/serializer/src/main/java/it/angrybear/yagl/utils/ParserUtils.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ public final class ParserUtils {
5050
public static <C> @NotNull String classToType(final @NotNull Class<C> coreClass, final @NotNull Class<? extends C> toConvert) {
5151
final String mainClassName = coreClass.getSimpleName();
5252
String name = toConvert.getSimpleName();
53+
if (name.startsWith(mainClassName)) name = name.substring(mainClassName.length());
5354
if (name.endsWith(mainClassName)) name = name.substring(0, name.length() - mainClassName.length());
55+
if (name.equals("Impl")) name = "default";
5456
name = FileUtils.formatStringToYaml(name);
5557
return name.replace("-", "_").toUpperCase();
5658
}

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[versions]
22
delombok = "8.4"
33

4-
fulmicollection = "1.5.1"
5-
yamlparser = "1.6.1"
4+
fulmicollection = "1.5.2"
5+
yamlparser = "1.6.2"
66

77
spigot = "1.14-R0.1-SNAPSHOT"
88
spigot_obsolete = "1.8.8-R0.1-SNAPSHOT"
@@ -14,7 +14,7 @@ annotations = "24.1.0"
1414

1515
junit = "5.9.1"
1616
mockito = "4.11.0"
17-
jbukkit = "2.0"
17+
jbukkit = "2.1"
1818

1919
[libraries]
2020
fulmicollection = { module = "it.fulminazzo:FulmiCollection", version.ref = "fulmicollection" }

gui/base/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dependencies {
2+
api project(':item:item-base')
3+
}

0 commit comments

Comments
 (0)