auto-pipeline

repository·main·Indexed 41 days ago

https://github.com/foldright/auto-pipeline

A Java annotation processor that automatically generates pipeline components for interfaces using the Chain of Responsibility pattern. It enables the creation of extensible, type-safe processing chains with zero runtime overhead by generating handler, pipeline, and context classes (version 0.4.0). Features include the @AutoPipeline annotation for code generation and @PipelineDirection to control execution flow as either FORWARD or REVERSE.

Tokens
5.9K
Snippets
17
Records
22
Agent score
49%

What's inside auto-pipeline

  1. Overview of auto-pipeline

    main

    auto-pipeline is a code generator that uses a Java Annotation Processor to automatically generate Pipeline implementations for your interfaces. It is inspired by Google's Auto project and helps developers implement the Pipeline (Chain of Responsibility) pattern with minimal boilerplate, making components more extensible and maintainable.

    Key Features:

    • Automatically generates handler interfaces, pipeline implementations, and context objects at compile time.
    • Reduces manual boilerplate for implementing complex chains of responsibility.
    • Supports Java 8 and higher.
  2. How auto-pipeline works: Annotating interfaces and generating code

    main

    To generate a pipeline, apply the @AutoPipeline annotation to your interface. During compilation, the auto-pipeline-processor will generate several classes in a pipeline package corresponding to your interface.

    Example Interface:

    @AutoPipeline
    public interface ConfigSource {
        String get(String key);
    }

    Generated Components: If you annotate an interface named ConfigSource, the following files are generated:

    • ConfigSourceHandler: The interface you implement to create custom logic for the pipeline.
    • ConfigSourcePipeline: The actual chain of responsibility implementation.
    • ConfigSourceHandlerContext: The context passed to handlers to allow them to continue the chain.
    • AbstractConfigSourceHandlerContext / DefaultConfigSourceHandlerContext: Base implementations for the context.
  3. Control pipeline execution flow with @PipelineDirection

    main

    The @PipelineDirection annotation allows you to control whether methods in an @AutoPipeline are executed from head to tail (forward) or tail to head (reverse).

    Execution direction is determined by a hierarchy of rules:

    1. Method-level Direction

    When annotating a method within an @AutoPipeline interface:

    • @Direction.FORWARD: The method is called from head to tail.
    • @Direction.REVERSE: The method is called from tail to head.
    • No annotation: The method inherits the direction defined on the @AutoPipeline interface.
    • Constraint: FORWARD and REVERSE are mutually exclusive at the method level.

    2. Interface-level Direction

    When annotating the @AutoPipeline interface itself:

    • @Direction.FORWARD: All methods in the interface default to head-to-tail execution (unless overridden by a method-level annotation).
    • @Direction.REVERSE: All methods in the interface default to tail-to-head execution (unless overridden by a method-level annotation).
    • No annotation: Defaults to @Direction.FORWARD.
    • Constraint: FORWARD and REVERSE are mutually exclusive at the interface level.
  4. How auto-pipeline works: Annotating interfaces and generating components

    main

    auto-pipeline uses the Chain of Responsibility pattern to make interfaces extensible. By adding the @AutoPipeline annotation to an interface, the auto-pipeline-processor automatically generates several classes in a .pipeline subpackage:

    • [InterfaceName]Handler: The interface you implement to add new logic to the chain.
    • [InterfaceName]Pipeline: The actual implementation of your interface that manages the chain.
    • [InterfaceName]HandlerContext: The context passed to each handler to allow them to pass control to the next handler in the chain.
    • Abstract[InterfaceName]HandlerContext & Default[InterfaceName]HandlerContext: Base implementations for the context.

    Example: Annotating a ConfigSource interface generates ConfigSourceHandler, ConfigSourcePipeline, and related context classes.

    @AutoPipeline
    public interface ConfigSource {
        String get(String key);
    }
  5. How @AutoPipeline works and generates code

    main

    The @AutoPipeline annotation is applied to a business interface to implement the Chain of Responsibility pattern automatically. When you compile your code, the auto-pipeline-processor generates five files in a pipeline subpackage:

    1. [InterfaceName]Handler.java: The responsibility interface that you implement to add logic to the chain.
    2. [InterfaceName]Pipeline.java: The actual chain implementation that implements your original interface.
    3. [InterfaceName]HandlerContext.java: The context interface for handlers.
    4. Abstract[InterfaceName]HandlerContext.java: An abstract base for the context.
    5. Default[InterfaceName]HandlerContext.java: The default implementation of the context.

    By annotating an interface, you gain a structured way to compose multiple handlers into a single pipeline.

    @AutoPipeline
    public interface ConfigSource {
        String get(String key);
    }
  6. Use @Direction to specify execution order

    main

    You can use @Direction.FORWARD or @Direction.REVERSE to explicitly set the execution flow for your pipeline methods or the entire interface. By default, pipelines operate in FORWARD mode.

    // Example of interface-level direction
    @AutoPipeline
    @Direction.REVERSE
    public interface MyReversePipeline {
        // This method will follow the interface direction (REVERSE)
        void stepOne();
    
        // This method overrides the interface to run FORWARD
        @Direction.FORWARD
        void stepTwo();
    }
  7. Install auto-pipeline dependencies

    main

    To use auto-pipeline, you must add both the auto-pipeline-annotations dependency (for the @AutoPipeline annotation) and configure the auto-pipeline-processor in your build tool's annotation processor path.

    Prerequisites:

    • Java 8 or higher.
    ### For Maven
    
    ```xml
    <dependencies>
        <!-- @AutoPipeline annotation -->
        <dependency>
            <groupId>com.foldright.auto-pipeline</groupId>
            <artifactId>auto-pipeline-annotations</artifactId>
            <version>0.4.0</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- Configure the annotation processor -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>com.foldright.auto-pipeline</groupId>
                            <artifactId>auto-pipeline-processor</artifactId>
                            <version>0.4.0</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

    For Gradle (Kotlin DSL)

    compileOnly("com.foldright.auto-pipeline:auto-pipeline-annotations:0.4.0")
    // auto-pipeline annotation processor will generate pipeline classes for interfaces
    annotationProcessor("com.foldright.auto-pipeline:auto-pipeline-processor:0.4.0")

    For Gradle (Groovy DSL)

    compileOnly 'com.foldright.auto-pipeline:auto-pipeline-annotations:0.4.0'
    annotationProcessor 'com.foldright.auto-pipeline:auto-pipeline-processor:0.4.0'
  8. Install auto-pipeline via Maven or Gradle

    main

    To use auto-pipeline, you must add both the auto-pipeline-annotations dependency (for use in your code) and the auto-pipeline-processor (to generate the pipeline classes during compilation).

    Maven Configuration

    Add the annotation dependency to your <dependencies> and configure the maven-compiler-plugin with the annotationProcessorPaths to include the processor.

    Gradle Configuration

    Use compileOnly for the annotations and annotationProcessor for the processor. This ensures zero runtime overhead as the dependencies are only needed at compile time.

    <!-- Maven -->
    <dependencies>
        <dependency>
            <groupId>com.foldright.auto-pipeline</groupId>
            <artifactId>auto-pipeline-annotations</artifactId>
            <version>0.4.0</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>com.foldright.auto-pipeline</groupId>
                            <artifactId>auto-pipeline-processor</artifactId>
                            <version>0.4.0</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    /* Gradle Kotlin DSL */
    compileOnly("com.foldright.auto-pipeline:auto-pipeline-annotations:0.4.0")
    annotationProcessor("com.foldright.auto-pipeline:auto-pipeline-processor:0.4.0")
    
    /* Gradle Groovy DSL */
    compileOnly 'com.foldright.auto-pipeline:auto-pipeline-annotations:0.4.0'
    annotationProcessor 'com.foldright.auto-pipeline:auto-pipeline-processor:0.4.0'