Skip to content

Commit

Permalink
Merge branch 'feat-data-gui' into dev
Browse files Browse the repository at this point in the history
# Conflicts:
#	build.gradle
#	common/base/src/main/java/it/angrybear/yagl/utils/ObjectUtils.java
  • Loading branch information
fulminazzo committed Dec 7, 2024
2 parents 5efb2e3 + 0e0faf9 commit 55e1bdd
Show file tree
Hide file tree
Showing 73 changed files with 2,654 additions and 266 deletions.
75 changes: 41 additions & 34 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ plugins {
id 'io.freefair.lombok' version libs.versions.delombok
}

final def TEST_MODULE = 'testing'
final def DEMO_MODULE = 'demo'
final def VERSION_VARIABLE = 'MINECRAFT_VERSION'

group = 'it.angrybear'
version = '4.0'

final def TEST_MODULE = "testing"
final def VERSION_VARIABLE = "MINECRAFT_VERSION"

allprojects {
apply plugin: 'java-library'
apply plugin: 'maven-publish'
Expand All @@ -26,7 +27,7 @@ allprojects {
def obsolete_version = libs.versions.spigot.obsolete.get()

this.ext.getParentFromProject = { project ->
return new HashMap<>(project.getProperties()).get("parent")
return new HashMap<>(project.getProperties()).get('parent')
}

this.ext.getProjectGroupId = {
Expand All @@ -37,7 +38,7 @@ allprojects {
tmp = getParentFromProject(tmp)
}
if (groupId.size() > 0)
groupId = "." + groupId.substring(0, groupId.length() - 1)
groupId = ".${groupId.substring(0, groupId.length() - 1)}"
return "${rootProject.group}${groupId}"
}

Expand All @@ -50,18 +51,18 @@ allprojects {
repositories {
mavenCentral()
maven {
name = "spigotmc-repo"
name = 'spigotmc-repo'
url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
}
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' }
maven { url = 'https://oss.sonatype.org/content/repositories/central' }
maven {
name = "JitPack"
url = "https://jitpack.io"
name = 'JitPack'
url = 'https://jitpack.io'
}
maven {
name = "Fulminazzo repository"
url = "https://repo.fulminazzo.it/releases"
name = 'Fulminazzo repository'
url = 'https://repo.fulminazzo.it/releases'
}
}

Expand All @@ -75,75 +76,76 @@ allprojects {

def projectName = project.name

if (projectName.contains("serializer")) api(libs.yamlparser)
if (projectName.contains('serializer')) api(libs.yamlparser)

if (projectName.contains("bukkit")) {
if (projectName.contains('bukkit')) {
compileOnly libs.spigot
testCompileOnly libs.spigot.latest
testRuntimeOnly "org.spigotmc:spigot-api:${latest_version}"

String numVersion = latest_version.substring(2, latest_version.indexOf(".", 2))
def index = numVersion.indexOf("-")
String numVersion = latest_version.substring(2, latest_version.indexOf('.', 2))
def index = numVersion.indexOf('-')
if (index != -1) numVersion = numVersion.substring(0, index)
if (Double.valueOf(numVersion) >= 13) testImplementation libs.jbukkit
else testImplementation libs.jbukkit.legacy
}

if (projectName.contains("legacy")) {
if (projectName.contains('legacy')) {
testCompileOnly libs.spigot.legacy
testRuntimeOnly "org.spigotmc:spigot-api:${legacy_version}"

testImplementation libs.jbukkit.legacy
}

if (projectName.contains("obsolete")) {
if (projectName.contains('obsolete')) {
testCompileOnly libs.spigot.obsolete
testRuntimeOnly "org.spigotmc:spigot-api:${obsolete_version}"

testImplementation libs.jbukkit.legacy
}

if (projectName.contains("-")) {
def name = projectName.substring(0, projectName.indexOf("-"))
def id = projectName.substring(projectName.indexOf("-") + 1)
if (!projectName.contains("base")) api(project(":${name}:${name}-base"))
if (name != "common" && id != "legacy" && id != "obsolete")
if (projectName.contains('-')) {
def name = projectName.substring(0, projectName.indexOf('-'))
def id = projectName.substring(projectName.indexOf('-') + 1)
if (!projectName.contains('base')) api(project(":${name}:${name}-base"))
if (name != 'common' && id != 'legacy' && id != 'obsolete')
api(project(":common:common-${id}"))
}

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

testCompileOnly libs.lombok
testAnnotationProcessor libs.lombok

if (!project.name.equals(TEST_MODULE)) testImplementation project(":" + TEST_MODULE)
if (project.name != TEST_MODULE) testImplementation project(":${TEST_MODULE}")

if (project.name == DEMO_MODULE)
rootProject.subprojects.findAll { it.name != TEST_MODULE && it.name != DEMO_MODULE }
.each { implementation project(it.path) }
}

if (project.name.equals(TEST_MODULE)) return
if (project.name == TEST_MODULE) return

test {
def projectName = project.name

if (System.getenv(VERSION_VARIABLE) == null) {
if (projectName.contains("bukkit")) environment VERSION_VARIABLE, latest_version
else if (projectName.contains("legacy")) environment VERSION_VARIABLE, legacy_version
else if (projectName.contains("obsolete")) environment VERSION_VARIABLE, obsolete_version
if (projectName.contains('bukkit')) environment VERSION_VARIABLE, latest_version
else if (projectName.contains('legacy')) environment VERSION_VARIABLE, legacy_version
else if (projectName.contains('obsolete')) environment VERSION_VARIABLE, obsolete_version
}

def env = System.getenv(VERSION_VARIABLE)
if (env != null) println "Testing ${projectName} with Minecraft ${env}"
useJUnitPlatform()
}

tasks.register("testBukkit") {
tasks.register('testBukkit') {
final def minecraftVersion = getMinecraftVersion()
println "Using Minecraft version ${minecraftVersion}"
latest_version = minecraftVersion
legacy_version = minecraftVersion
obsolete_version = minecraftVersion

subprojects.findAll { it.path.contains("bukkit") }.each { dependsOn "${it.path}:test" }
subprojects.findAll { it.path.contains('bukkit') }.each {dependsOn "${it.path}:test" }
}

tasks.register('sourcesJar', Jar) {
Expand Down Expand Up @@ -171,10 +173,10 @@ allprojects {

repositories {
maven {
url "https://repo.fulminazzo.it/releases"
url 'https://repo.fulminazzo.it/releases'
credentials {
username = System.getenv("REPO_USERNAME")
password = System.getenv("REPO_PASSWORD")
username = System.getenv('REPO_USERNAME')
password = System.getenv('REPO_PASSWORD')
}
authentication {
basic(BasicAuthentication)
Expand All @@ -184,6 +186,11 @@ allprojects {
}
}

dependencies {
subprojects.findAll { it.name != TEST_MODULE && it.name != DEMO_MODULE } .each { api project(it.path) }
implementation project(":${DEMO_MODULE}")
}

tasks.register("aggregateJavaDoc") {
allprojects.forEach { dependsOn "${it.path}:javadoc" }
doLast {
Expand Down
3 changes: 2 additions & 1 deletion common/base/src/main/java/it/angrybear/yagl/ClassEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ private void checkValues() {
if (!this.values.isEmpty()) return;
for (Field field : this.clazz.getDeclaredFields())
if (field.getType().equals(this.clazz))
this.values.put(field.getName().toUpperCase(), ReflectionUtils.get(field, this.clazz));
ReflectionUtils.get(field, this.clazz).ifPresent(o ->
this.values.put(field.getName().toUpperCase(), (T) o));
}
}
}
80 changes: 51 additions & 29 deletions common/base/src/main/java/it/angrybear/yagl/utils/ObjectUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,39 +66,61 @@ public static <T, O extends T> O copy(final @NotNull T t, @NotNull Class<O> claz
clazz.getCanonicalName(), clazz.getCanonicalName()));
}

Refl<O> object = new Refl<>(clazz, new Object[0]);
for (final Field field : object.getNonStaticFields())
final Refl<O> object = new Refl<>(clazz, new Object[0]);
for (final Field field : object.getNonStaticFields()) {
field.setAccessible(true);
try {
Object obj1 = ReflectionUtils.get(field, t);
if (obj1 instanceof Collection) {
Class<?> tmpClass = obj1.getClass();
// In the case of creation with Arrays.asList()
if (tmpClass.getCanonicalName().equals(Arrays.class.getCanonicalName() + ".ArrayList"))
tmpClass = ArrayList.class;
Class<Collection<Object>> finalClass = (Class<Collection<Object>>) tmpClass;
obj1 = ((Collection<?>) obj1).stream()
.collect(Collectors.toCollection(() -> new Refl<>(finalClass, new Object[0]).getObject()));
} else if (obj1 instanceof Map) {
Map<Object, Object> map = new HashMap<>();
((Map<Object, Object>) obj1).putAll(map);
obj1 = map;
} else if (obj1 != null)
if (obj1.getClass().isArray()) {
Object[] tmp = (Object[]) obj1;
Object[] arr = (Object[]) Array.newInstance(obj1.getClass().getComponentType(), tmp.length);
System.arraycopy(tmp, 0, arr, 0, arr.length);
obj1 = arr;
} else
try {
Method copy = obj1.getClass().getDeclaredMethod("copy");
obj1 = ReflectionUtils.setAccessible(copy).invoke(obj1);
} catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException ignored) {}
object.setFieldObject(field, obj1);
} catch (IllegalArgumentException ignored) {}

ReflectionUtils.get(field, t).map(obj1 -> {
if (obj1 == null) return null;
else if (obj1 instanceof Collection) return copyCollection(obj1);
else if (obj1 instanceof Map) return copyMap(obj1);
else if (obj1.getClass().isArray()) return copyArray(obj1);
else return copyWithMethod(obj1);
}).ifPresent(obj1 -> object.setFieldObject(field, obj1));
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("Can not set")) throw e;
}
}
return object.getObject();
}

private static @NotNull Object[] copyArray(final @NotNull Object obj1) {
Object[] tmp = (Object[]) obj1;
Object[] arr = (Object[]) Array.newInstance(obj1.getClass().getComponentType(), tmp.length);
for (int i = 0; i < tmp.length; i++) arr[i] = copyWithMethod(tmp[i]);
return arr;
}

private static @NotNull Map<Object, Object> copyMap(final @NotNull Object obj1) {
Map<Object, Object> map = new HashMap<>();
((Map<Object, Object>) obj1).forEach((k, v) ->
map.put(copyWithMethod(k), copyWithMethod(v)));
return map;
}

private static @NotNull Collection<?> copyCollection(final @NotNull Object obj1) {
Class<?> tmpClass = obj1.getClass();
// In the case of creation with Arrays.asList()
if (tmpClass.getCanonicalName().equals(Arrays.class.getCanonicalName() + ".ArrayList"))
tmpClass = ArrayList.class;
Class<Collection<Object>> finalClass = (Class<Collection<Object>>) tmpClass;
return ((Collection<?>) obj1).stream()
.map(ObjectUtils::copyWithMethod)
.collect(Collectors.toCollection(() -> new Refl<>(finalClass, new Object[0]).getObject()));
}

private static @Nullable Object copyWithMethod(final @Nullable Object obj1) {
try {
if (obj1 == null) return null;
Method copy = obj1.getClass().getDeclaredMethod("copy");
return ReflectionUtils.setAccessible(copy)
.map(m -> m.invoke(obj1))
.orElseGet(obj1);
} catch (NoSuchMethodException e) {
return obj1;
}
}

/**
* Prints the given object in a JSON format.
* If the object (or an object contained in it) is "empty",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

Expand Down Expand Up @@ -36,21 +34,46 @@ void testCopyOfData() {
assertNotEquals(c1.array, c2.array);
assertArrayEquals(c1.array, c2.array);
assertNotEquals(c1.copiable, c2.copiable);
assertEquals(c1.map, c2.map);
// Try removal from the first map
c1.map.remove("hello");
assertEquals("world", c2.map.get("hello"));
}

@Test
void testCopyThrowsIllegalArgument() {
Throwable exception = assertThrowsExactly(IllegalArgumentException.class, () ->
ObjectUtils.copy(new GeneralCopyException()));
assertEquals("Everything good", exception.getMessage());
}

private static class GeneralCopy {
Map<String, String> map = new HashMap<String, String>(){{
put("hello", "world");
}};
List<String> list = Arrays.asList("hello", "world");
String[] array = new String[]{"hello", "world"};
GeneralCopiable copiable = new GeneralCopiable();
}

private static class GeneralCopyException {
GeneralCopiableException copiable = new GeneralCopiableException();
}

private static class GeneralCopiable {

public GeneralCopiable copy() {
return new GeneralCopiable();
}
}

private static class GeneralCopiableException {

public GeneralCopiable copy() {
throw new IllegalArgumentException("Everything good");
}
}

private static class CopyIterableImpl { }

private static class CopyIterable implements Iterable<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import it.angrybear.yagl.utils.ParserUtils;
import it.fulminazzo.fulmicollection.interfaces.functions.TriConsumer;
import it.fulminazzo.fulmicollection.objects.Refl;
import it.fulminazzo.yamlparser.configuration.ConfigurationSection;
import it.fulminazzo.yamlparser.configuration.IConfiguration;
import it.fulminazzo.yamlparser.parsers.CallableYAMLParser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* This parser allows parsing an object using the {@link CallableYAMLParser} methods.
* However, it forces the saved object to store a <i>type</i> field, that contains the name of the class of the original object.
* However, it forces the saved object to store a <i>type</i> field, that contains the class name of the original object.
* Upon loading, this class is retrieved (and will throw errors for invalid values) to recreate the object.
*
* @param <C> the type parameter
Expand All @@ -23,12 +25,7 @@ public abstract class TypedParser<C> extends CallableYAMLParser<C> {
* @param clazz the clazz
*/
public TypedParser(final @NotNull Class<C> clazz) {
super(clazz, (c) -> {
String type = c.getString(TYPE_FIELD);
if (type == null) throw new IllegalArgumentException(String.format("'%s' cannot be null", TYPE_FIELD));
Class<? extends C> clz = ParserUtils.typeToClass(clazz, type);
return new Refl<>(clz, new Object[0]).getObject();
});
super(clazz, c -> getObjectFromType(clazz, c));
}

@SuppressWarnings("unchecked")
Expand All @@ -40,4 +37,23 @@ protected TriConsumer<IConfiguration, String, C> getDumper() {
c.set(s + "." + TYPE_FIELD, ParserUtils.classToType(getOClass(), (Class<? extends C>) g.getClass()));
};
}

/**
* Tries to get the corresponding {@link #TYPE_FIELD} type from the given section, and coverts it to an instance.
* Throws an {@link IllegalArgumentException} in case no type is provided or no class is found.
*
* @param <T> the type of the object
* @param objectClass the object class
* @param section the section
* @param parameters the parameters for the constructor
* @return the object
*/
protected static <T> T getObjectFromType(final @NotNull Class<T> objectClass,
final @NotNull ConfigurationSection section,
final Object @Nullable ... parameters) {
String type = section.getString(TYPE_FIELD);
if (type == null) throw new IllegalArgumentException(String.format("'%s' cannot be null", TYPE_FIELD));
Class<? extends T> clazz = ParserUtils.typeToClass(objectClass, type);
return new Refl<>(clazz, parameters).getObject();
}
}
Loading

0 comments on commit 55e1bdd

Please sign in to comment.