Collection.java 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package me.lortseam.completeconfig.data;
  2. import lombok.extern.log4j.Log4j2;
  3. import me.lortseam.completeconfig.api.ConfigEntryContainer;
  4. import me.lortseam.completeconfig.api.ConfigGroup;
  5. import me.lortseam.completeconfig.data.structure.FlatDataPart;
  6. import me.lortseam.completeconfig.data.text.TranslationIdentifier;
  7. import me.lortseam.completeconfig.exception.IllegalAnnotationTargetException;
  8. import net.minecraft.text.Text;
  9. import java.lang.reflect.Constructor;
  10. import java.lang.reflect.InvocationTargetException;
  11. import java.lang.reflect.Modifier;
  12. import java.util.*;
  13. import java.util.stream.Collectors;
  14. @Log4j2
  15. public class Collection implements FlatDataPart<ConfigMap> {
  16. protected final TranslationIdentifier translation;
  17. private final EntryMap entries;
  18. private final CollectionMap collections;
  19. Collection(TranslationIdentifier translation) {
  20. this.translation = translation;
  21. entries = new EntryMap(translation);
  22. collections = new CollectionMap(translation);
  23. }
  24. public Text getText() {
  25. return translation.toText();
  26. }
  27. public java.util.Collection<Entry> getEntries() {
  28. return Collections.unmodifiableCollection(entries.values());
  29. }
  30. public java.util.Collection<Collection> getCollections() {
  31. return Collections.unmodifiableCollection(collections.values());
  32. }
  33. void resolve(ConfigEntryContainer container) {
  34. entries.resolve(container);
  35. List<ConfigEntryContainer> containers = new ArrayList<>();
  36. for (Class<? extends ConfigEntryContainer> clazz : container.getConfigClasses()) {
  37. containers.addAll(Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
  38. if (container.isConfigPOJO()) {
  39. return ConfigEntryContainer.class.isAssignableFrom(field.getType());
  40. }
  41. if (field.isAnnotationPresent(ConfigEntryContainer.Transitive.class)) {
  42. if (!ConfigEntryContainer.class.isAssignableFrom(field.getType())) {
  43. throw new IllegalAnnotationTargetException("Transitive entry " + field + " must implement ConfigEntryContainer");
  44. }
  45. return true;
  46. }
  47. return false;
  48. }).map(field -> {
  49. if (!field.isAccessible()) {
  50. field.setAccessible(true);
  51. }
  52. try {
  53. return (ConfigEntryContainer) field.get(container);
  54. } catch (IllegalAccessException e) {
  55. throw new RuntimeException(e);
  56. }
  57. }).collect(Collectors.toList()));
  58. if (container.isConfigPOJO()) {
  59. resolve(Arrays.stream(clazz.getDeclaredClasses()).filter(nestedClass -> {
  60. return ConfigEntryContainer.class.isAssignableFrom(nestedClass) && Modifier.isStatic(nestedClass.getModifiers());
  61. }).map(nestedClass -> {
  62. try {
  63. Constructor<? extends ConfigEntryContainer> constructor = (Constructor<? extends ConfigEntryContainer>) nestedClass.getDeclaredConstructor();
  64. if (!constructor.isAccessible()) {
  65. constructor.setAccessible(true);
  66. }
  67. return constructor.newInstance();
  68. } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
  69. throw new RuntimeException("Failed to instantiate nested config entry container class", e);
  70. }
  71. }).filter(Objects::nonNull).collect(Collectors.toList()));
  72. }
  73. }
  74. containers.addAll(Arrays.asList(container.getTransitiveContainers()));
  75. resolve(containers);
  76. }
  77. protected void resolve(java.util.Collection<ConfigEntryContainer> containers) {
  78. for (ConfigEntryContainer c : containers) {
  79. if (c instanceof ConfigGroup) {
  80. collections.resolve((ConfigGroup) c);
  81. } else {
  82. resolve(c);
  83. }
  84. }
  85. }
  86. @Override
  87. public Iterable<ConfigMap> getChildren() {
  88. return Arrays.asList(entries, collections);
  89. }
  90. boolean isEmpty() {
  91. return entries.isEmpty() && collections.isEmpty();
  92. }
  93. }