BaseCollection.java 4.1 KB

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