From 6e0a0fe952b37e8c2a3b2537106bca30fd221761 Mon Sep 17 00:00:00 2001 From: Daniel Mangold Date: Sun, 17 Nov 2024 15:39:14 +0100 Subject: [PATCH] Add more missing documentation --- .../SolutionMergingClassTransformer.java | 29 ++++++++++++ .../transform/SubmissionClassVisitor.java | 44 +++++++++++++++++++ .../transform/util/TransformationContext.java | 10 +++++ 3 files changed, 83 insertions(+) diff --git a/tutor/src/main/java/org/tudalgo/algoutils/transform/SolutionMergingClassTransformer.java b/tutor/src/main/java/org/tudalgo/algoutils/transform/SolutionMergingClassTransformer.java index 9e67131..d393dc8 100644 --- a/tutor/src/main/java/org/tudalgo/algoutils/transform/SolutionMergingClassTransformer.java +++ b/tutor/src/main/java/org/tudalgo/algoutils/transform/SolutionMergingClassTransformer.java @@ -76,6 +76,12 @@ public SolutionMergingClassTransformer(String projectPrefix, String... available this(new Builder(projectPrefix, availableSolutionClasses)); } + /** + * Constructs a new {@link SolutionMergingClassTransformer} instance with config settings from + * the given builder. + * + * @param builder the builder object + */ @SuppressWarnings("unchecked") private SolutionMergingClassTransformer(Builder builder) { Map solutionClasses = new HashMap<>(); @@ -104,6 +110,9 @@ public void transform(ClassReader reader, ClassWriter writer) { reader.accept(new SubmissionClassVisitor(writer, transformationContext, submissionClassName), 0); } + /** + * (Internal) Configuration keys + */ public enum Config { PROJECT_PREFIX(null), SOLUTION_CLASSES(null), @@ -116,10 +125,19 @@ public enum Config { } } + /** + * Builder for {@link SolutionMergingClassTransformer}. + */ public static class Builder { private final Map configuration = new EnumMap<>(Config.class); + /** + * Constructs a new {@link Builder}. + * + * @param projectPrefix the root package containing all submission classes, usually the sheet number + * @param solutionClasses the list of solution class names (fully qualified) to use + */ public Builder(String projectPrefix, String... solutionClasses) { for (Config config : Config.values()) { configuration.put(config, config.defaultValue); @@ -128,11 +146,22 @@ public Builder(String projectPrefix, String... solutionClasses) { configuration.put(Config.SOLUTION_CLASSES, List.of(solutionClasses)); } + /** + * Sets the threshold for matching submission classes to solution classes via similarity matching. + * + * @param similarity the new similarity threshold + * @return the builder object + */ public Builder setSimilarity(double similarity) { configuration.put(Config.SIMILARITY, similarity); return this; } + /** + * Constructs the transformer. + * + * @return the configured {@link SolutionMergingClassTransformer} object + */ public SolutionMergingClassTransformer build() { return new SolutionMergingClassTransformer(this); } diff --git a/tutor/src/main/java/org/tudalgo/algoutils/transform/SubmissionClassVisitor.java b/tutor/src/main/java/org/tudalgo/algoutils/transform/SubmissionClassVisitor.java index 876cfbd..2dd125e 100644 --- a/tutor/src/main/java/org/tudalgo/algoutils/transform/SubmissionClassVisitor.java +++ b/tutor/src/main/java/org/tudalgo/algoutils/transform/SubmissionClassVisitor.java @@ -49,6 +49,37 @@ * * All of these options can be enabled / disabled via {@link SubmissionExecutionHandler}. * + *

+ * + * Generally, the body of a transformed method would look like this in Java source code: + *
+ * SubmissionExecutionHandler.Internal submissionExecutionHandler = SubmissionExecutionHandler.getInstance().new Internal();
+ * MethodHeader methodHeader = new MethodHeader(...);  // parameters are hardcoded during transformation
+ *
+ * if (submissionExecutionHandler.logInvocation(methodHeader)) {
+ *     submissionExecutionHandler.addInvocation(new Invocation(...)  // new Invocation() if constructor or static method
+ *         .addParameter(...)  // for each parameter
+ *         ...);
+ * }
+ * if (submissionExecutionHandler.useSubstitution(methodHeader)) {  // if not constructor
+ *     submissionExecutionHandler.getSubstitution(methodHeader)
+ *         .execute(new Invocation(...) ...);  // same as above
+ * }
+ * if (submissionExecutionHandler.useSubmissionImpl(methodHeader)) {
+ *     ...  // submission code
+ * } else {
+ *     ...  // solution code
+ * }
+ * 
+ * If no solution class is associated with the submission class, the submission code is executed unconditionally. + *
+ * Additionally, the following methods are injected into the submission class: + *
+ * public static ClassHeader getOriginalClassHeader() {...}
+ * public static Set<FieldHeader> getOriginalFieldHeaders() {...}
+ * public static Set<MethodHeader> getOriginalMethodHeaders() {...}
+ * 
+ * * @see SubmissionExecutionHandler * @author Daniel Mangold */ @@ -364,6 +395,7 @@ private void buildInvocation(Type[] argumentTypes) { /** * Adds all remaining fields and methods from the solution class that have not already * been visited (e.g., lambdas). + * Injects methods for retrieving the original class, field and method headers during runtime. */ @Override public void visitEnd() { @@ -389,6 +421,10 @@ public void visitEnd() { super.visitEnd(); } + /** + * Injects a static method {@code getOriginalClassHeader()} into the submission class. + * This injected method returns the original class header of the class pre-transformation. + */ private void classMetadata() { ClassHeader classHeader = submissionClassInfo.getOriginalClassHeader(); Label startLabel = new Label(); @@ -412,6 +448,10 @@ private void classMetadata() { mv.visitMaxs(maxStack, 1); } + /** + * Injects a static method {@code getOriginalFieldHeaders()} into the submission class. + * This injected method returns the set of original field headers of the class pre-transformation. + */ private void fieldMetadata() { Set fieldHeaders = submissionClassInfo.getOriginalFieldHeaders(); Label startLabel = new Label(); @@ -455,6 +495,10 @@ private void fieldMetadata() { mv.visitMaxs(maxStack, 1); } + /** + * Injects a static method {@code getOriginalMethodHeaders()} into the submission class. + * This injected method returns the set of original method headers of the class pre-transformation. + */ private void methodMetadata() { Set methodHeaders = submissionClassInfo.getOriginalMethodHeaders(); Label startLabel = new Label(); diff --git a/tutor/src/main/java/org/tudalgo/algoutils/transform/util/TransformationContext.java b/tutor/src/main/java/org/tudalgo/algoutils/transform/util/TransformationContext.java index 281514b..f6c32a6 100644 --- a/tutor/src/main/java/org/tudalgo/algoutils/transform/util/TransformationContext.java +++ b/tutor/src/main/java/org/tudalgo/algoutils/transform/util/TransformationContext.java @@ -20,10 +20,20 @@ public record TransformationContext( Map submissionClasses ) { + /** + * Returns the project prefix. + * + * @return the project prefix + */ public String getProjectPrefix() { return (String) configuration.get(SolutionMergingClassTransformer.Config.PROJECT_PREFIX); } + /** + * Returns the minimum similarity threshold. + * + * @return the minimum similarity threshold + */ public double getSimilarity() { return (Double) configuration.get(SolutionMergingClassTransformer.Config.SIMILARITY); }