package com.sora.util.akatsuki;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.sora.util.akatsuki.ArgConcludingBuilder.VoidBuilder;
/**
* Compile time configuration for {@link Arg}, to be used on classes with field
* annotated with {@code Arg}
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.CLASS)
public @interface ArgConfig {
enum BuilderType {
/**
* Fluent builder, this is the recommended builder for general usage<br>
* EX:<br>
* {@code a(1).b(2).c(3)}, where {@code a()} returns a class with only
* {@code b()} visible <br>
* This builder is the safe without runtime check as it implicitly
* forbid you from omitting mandatory args
*
*/
// TODO for next release
// FLUENT(ReturnType.SUBCLASSED,
// Check.NONE), /**
// * Builder returns itself for chaining, no
// * ordering is enforced, checked is done at
// * runtime<br>
// * EX:<br>
// * {@code }a(2).b(2).a(1).c(3) } , notice that
// * repeated args and unordered invocation are
// * allowed<br>
// * When a mandatory field is omitted, an
// * {@link IllegalArgumentException} is thrown
// */
CHAINED_CHECKED(ReturnType.CHAINED,
Check.RUNTIME), /**
* Builder setters returns itself, checking is
* done at runtime
*/
CHAINED_UNCHECKED(ReturnType.CHAINED,
Check.NONE), /**
* Builder setters return void, behaves like
* {@link #CHAINED_CHECKED} but without chaining
*/
CHECKED(ReturnType.VOID,
Check.RUNTIME), /**
* Builder returns void, behaves like
* {@link #CHAINED_UNCHECKED} but without
* chaining
*/
UNCHECKED(ReturnType.VOID, Check.NONE);
final ReturnType returnType;
final Check check;
BuilderType(ReturnType returnType, Check check) {
this.returnType = returnType;
this.check = check;
}
enum ReturnType {
CHAINED, SUBCLASSED, VOID
}
enum Check {
RUNTIME, NONE
// TODO compile time maybe? I guess we can get caller(traverse the
// entire source tree) and then check for incomplete calls.... but
// that's writing half a compiler ....
}
}
/**
* Specifies what type of builder will be genrerated, see
* {@link ArgConfig.BuilderType} for all supported types
*/
BuilderType type() default BuilderType.CHAINED_CHECKED;
@interface BuilderNamingRules {
enum Type {
ANDROID, UNDERSCORE, SIMPLE, TEMPLATE
}
Type value() default Type.SIMPLE;
String splitWith() default "";
String template();
}
interface MethodTransformation {
String transform(String name);
}
/**
* Naming rules to be used while the builder class is generated, the rules
* are applied in order of declaration (array order) to each element.For
* example, to add a prefix to a field while keeping the camelCase,
* something like this can be used: <br>
* 1. Transform the first letter to upper case<br>
* and the second rule to append
*
*/
// BuilderNamingRules[]namingRules() default {};
// TODO next version, no implementation yet
// enum FieldNameConvention {
// /**
// * Fields prefixed with m for member (ex: mFoo, mBar, mFooBar)
// */
// ANDROID,
//
// /**
// * Fields with no prefix (ex: foo, bar, fooBar)
// */
// SIMPLE
// }
//
// /**
// * Defines how field names are transformed when the builder is generated
// */
// FieldNameConvention convention() default FieldNameConvention.SIMPLE;
/**
* Defines how builder method name are sorted
*/
enum Sort {
CODE, INDEX, LEXICOGRAPHICAL, RANDOM
}
/**
* Used in conjunction with {@link Sort} to specify order
*/
enum Order {
ASC, DSC
}
/**
* Defines the order of the generated builder methods
*/
Sort sort() default Sort.CODE;
/**
* The order of the {@link #sort()}, defaults to {@link Order#ASC}
*/
Order order() default Order.ASC;
Class<? extends ArgConcludingBuilder>concludingBuilder() default VoidBuilder.class;
/**
* Whether the class should be processed; useful for debugging
*/
boolean enabled() default true;
}