BaseCollection.java 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package me.lortseam.completeconfig.data;
  2. import com.google.common.collect.Iterables;
  3. import me.lortseam.completeconfig.api.ConfigContainer;
  4. import me.lortseam.completeconfig.api.ConfigGroup;
  5. import me.lortseam.completeconfig.data.structure.DataPart;
  6. import me.lortseam.completeconfig.data.structure.ParentDataPart;
  7. import me.lortseam.completeconfig.data.text.TranslationKey;
  8. import me.lortseam.completeconfig.exception.IllegalAnnotationTargetException;
  9. import me.lortseam.completeconfig.util.ReflectionUtils;
  10. import net.fabricmc.api.EnvType;
  11. import net.fabricmc.api.Environment;
  12. import org.apache.commons.lang3.ArrayUtils;
  13. import java.lang.reflect.InvocationTargetException;
  14. import java.lang.reflect.Modifier;
  15. import java.util.Arrays;
  16. import java.util.Collections;
  17. abstract class BaseCollection implements ParentDataPart {
  18. @Environment(EnvType.CLIENT)
  19. protected TranslationKey translation;
  20. private final EntrySet entries = new EntrySet(this);
  21. private final CollectionSet collections = new CollectionSet(this);
  22. public java.util.Collection<Entry> getEntries() {
  23. return Collections.unmodifiableCollection(entries);
  24. }
  25. public java.util.Collection<Collection> getCollections() {
  26. return Collections.unmodifiableCollection(collections);
  27. }
  28. void resolveContainer(ConfigContainer container) {
  29. entries.resolve(container);
  30. for (Class<? extends ConfigContainer> clazz : container.getConfigClasses()) {
  31. resolve(Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
  32. if (field.isAnnotationPresent(ConfigContainer.Transitive.class)) {
  33. if (!ConfigContainer.class.isAssignableFrom(field.getType())) {
  34. throw new IllegalAnnotationTargetException("Transitive field " + field + " must implement " + ConfigContainer.class.getSimpleName());
  35. }
  36. return !Modifier.isStatic(field.getModifiers()) || clazz == container.getClass();
  37. }
  38. return false;
  39. }).map(field -> {
  40. if (!field.isAccessible()) {
  41. field.setAccessible(true);
  42. }
  43. try {
  44. return (ConfigContainer) field.get(container);
  45. } catch (IllegalAccessException e) {
  46. throw new RuntimeException(e);
  47. }
  48. }).toArray(ConfigContainer[]::new));
  49. Class<?>[] nestedClasses = clazz.getDeclaredClasses();
  50. ArrayUtils.reverse(nestedClasses);
  51. resolve(Arrays.stream(nestedClasses).filter(nestedClass -> {
  52. if (nestedClass.isAnnotationPresent(ConfigContainer.Transitive.class)) {
  53. if (!ConfigContainer.class.isAssignableFrom(nestedClass)) {
  54. throw new IllegalAnnotationTargetException("Transitive " + nestedClass + " must implement " + ConfigContainer.class.getSimpleName());
  55. }
  56. if (!Modifier.isStatic(nestedClass.getModifiers())) {
  57. throw new IllegalAnnotationTargetException("Transitive " + nestedClass + " must be static");
  58. }
  59. return true;
  60. }
  61. return false;
  62. }).map(nestedClass -> {
  63. try {
  64. return (ConfigContainer) ReflectionUtils.instantiateClass(nestedClass);
  65. } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
  66. throw new RuntimeException("Failed to instantiate nested " + nestedClass, e);
  67. }
  68. }).toArray(ConfigContainer[]::new));
  69. }
  70. resolve(container.getTransitives());
  71. }
  72. protected void resolve(ConfigContainer... containers) {
  73. for (ConfigContainer container : containers) {
  74. if (container instanceof ConfigGroup) {
  75. collections.resolve((ConfigGroup) container);
  76. } else {
  77. resolveContainer(container);
  78. }
  79. }
  80. }
  81. @Override
  82. public Iterable<DataPart> getChildren() {
  83. return Iterables.concat(entries, collections);
  84. }
  85. boolean isEmpty() {
  86. return Iterables.size(getChildren()) == 0;
  87. }
  88. }