diff --git a/s-pipes-core/src/main/java/cz/cvut/spipes/modules/AnnotatedAbstractModule.java b/s-pipes-core/src/main/java/cz/cvut/spipes/modules/AnnotatedAbstractModule.java index 744cd522..bca26e2e 100644 --- a/s-pipes-core/src/main/java/cz/cvut/spipes/modules/AnnotatedAbstractModule.java +++ b/s-pipes-core/src/main/java/cz/cvut/spipes/modules/AnnotatedAbstractModule.java @@ -18,40 +18,67 @@ * {@link Parameter} annotation to indicate that they are configurable parameters. * The class will automatically detect these parameters, validate them, and populate * them with the appropriate values during the module's initialization. - * - *

The {@link #loadConfiguration()} method is overridden to handle this process. - * It identifies all fields annotated with {@link Parameter}, checks for duplicate - * parameter names, and uses the appropriate `Setter` and `Handler` implementations - * to assign values to the fields. */ public abstract class AnnotatedAbstractModule extends AbstractModule { private static final Logger log = LoggerFactory.getLogger(AnnotatedAbstractModule.class); + /** + * Loads the configuration for the module by scanning fields annotated with {@link Parameter} + * and setting their values using the appropriate {@link Setter} and {@link Handler} implementations. + * + *

This method is responsible for processing the fields declared in the class and its superclasses, + * that are annotated with {@link Parameter}. It ensures that each field is processed only once and + * verifies that no two fields share the same {@link Parameter#iri()}. If a duplicate is found, + * it throws a {@link RuntimeException}. + * + *

For each annotated field: + *

+ * + *

The method continues processing all declared fields, moving up through the class hierarchy + * until it reaches the {@code AnnotatedAbstractModule} class itself. + * + *

After all automatically configurable fields have been processed, it invokes the + * {@link #loadManualConfiguration()} method to allow subclasses to handle any custom configuration + * that requires manual intervention. + * + * @throws RuntimeException if two or more fields in the class hierarchy share the same + * {@link Parameter#iri()}. + */ @Override public void loadConfiguration() { - final Map vars = new HashMap<>(); - for (final Field f : this.getClass().getDeclaredFields()) { - final Parameter p = f.getAnnotation(Parameter.class); - if (p == null) { - continue; - } else if (vars.containsKey(p.iri())) { - throw new RuntimeException(String.format("Two parameters have same iri %s", p.iri())); - } else { - vars.put(p.iri(), f); - } - log.trace("Processing parameter {} ", f.getName()); + Class clazz = this.getClass(); + + while(clazz != AnnotatedAbstractModule.class){ + final Map vars = new HashMap<>(); + for (final Field f : clazz.getDeclaredFields()) { + final Parameter p = f.getAnnotation(Parameter.class); + if (p == null) { + continue; + } else if (vars.containsKey(p.iri())) { + throw new RuntimeException(String.format("Two parameters have same iri %s", p.iri())); + } else { + vars.put(p.iri(), f); + } + + log.trace("Processing parameter {} ", f.getName()); - Setter setter; - if (f.getType() == List.class) { - setter = new ListSetter(f, this); - } else { - setter = new FieldSetter(f, this); + Setter setter; + if (f.getType() == List.class) { + setter = new ListSetter(f, this); + } else { + setter = new FieldSetter(f, this); + } + HandlerRegistry handlerRegistry = HandlerRegistry.getInstance(); + Handler handler = handlerRegistry.getHandler(f.getType(), resource, executionContext, setter); + handler.setValueByProperty(ResourceFactory.createProperty(p.iri())); } - HandlerRegistry handlerRegistry = HandlerRegistry.getInstance(); - Handler handler = handlerRegistry.getHandler(f.getType(), resource, executionContext, setter); - handler.setValueByProperty(ResourceFactory.createProperty(p.iri())); + clazz = (Class) clazz.getSuperclass(); } loadManualConfiguration(); }