Skip to main content

Protected Regions

To avoid confusing errors during automated evaluation, Subato clients should prevent users from editing predefined elements in template files, such as method names and parameter types. Thus, a task can be configured with protected regions for defining readonly sections of the code.

Java tasks only

Protected regions are only supported for tasks configured with lang=java in meta.xml.

Manual Definition

Protected regions can be defined manually in template files using annotations. Set protectedRegions="enabled" in meta.xml first, then import the annotations in the file:

import de.hsrm.sls.subato.ext.*;

Fields, methods, types, and records can then be annotated with these annotations:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface ProtectedField {
}

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface ProtectedMethod {
// Whether the method body can be edited
public boolean enableBody() default false;
}

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface ProtectedType {
// Whether the class body can be edited
public boolean enableBody() default false;
}

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface ProtectedRecord {
// Whether the record body can be edited
public boolean enableBody() default false;

// Whether the components in the record header (canonical constructor) can be edited
public boolean enableComponents() default false;
}

Example

AL.java
import de.hsrm.sls.subato.ext.*;

@ProtectedType(enableBody = true)
public class AL<E> {
@ProtectedField
private long theSize;
private Object[] store;

@ProtectedMethod(enableBody = true)
AL() {
/* TODO */
}

@ProtectedMethod
long size() {
return theSize;
}

@ProtectedMethod(enableBody = true)
AL<E> add(E e) {
/* TODO */
}

AL<E> remove(E o) {
/* TODO */
}

private void enlargeStore(){
Object[] newStore = new Object[store.length+10];
for (long i=0;i<theSize;i++) newStore[i]=store[i];
store=newStore;
}

@ProtectedType
interface MyPredicate<A> {
boolean test(A v);
}

AL<E> filter(MyPredicate<E> p) {
/* TODO */
}

@ProtectedRecord(enableComponents = true)
record Pair<E, A>(/* TODO */) { }

<A> AL<Pair<E, A>> pairWith(AL<A> rs) {
/* TODO */
}
}

Automated Definition

Instead of annotating everything by hand, set protectedRegions="auto" in meta.xml. Protected regions are then configured automatically from the test files, using these rules:

  • Every method in a template file called from a test file is annotated with @ProtectedMethod
  • Every constructor in a template file used to instantiate an object in a test file is annotated with @ProtectedMethod
  • Every field accessed from a test file is annotated with @ProtectedField
  • Every class, record, interface or enum containing an element that matches any of the previously listed rules is annotated with either @ProtectedType (for classes, interfaces and enums) or @ProtectedRecord (for records).

@ProtectedMethod, @ProtectedType, and @ProtectedRecord are applied with enableBody = true, which produces the expected result in most cases. When it does not, override it with a manual annotation in the template file. These always take precedence over auto-detected ones. You can also exclude annotations that were automatically created by annotating the target element with @ProtectedIgnore.