Skip to content

πŸš€ auto-pipeline is a source code generator that auto generate the component's pipeline.

License

Notifications You must be signed in to change notification settings

foldright/auto-pipeline

Repository files navigation

auto-pipeline πŸš€

English | δΈ­ζ–‡

Github Workflow Build Status Github Workflow Build Status Coverage Status Java support License Maven Central GitHub release GitHub Stars GitHub Forks GitHub issues GitHub Contributors GitHub repo size gitpod: Ready to Code

Overview

auto-pipeline is a source code generator that automatically generates pipeline components for your interfaces. It helps keep your project smaller, simpler, and more extensible by leveraging the Chain of Responsibility pattern. πŸ’‘

auto-pipeline is implemented as an annotation-processor, inspired by Google's Auto. ❀️

Features

  • πŸš€ Zero Runtime Dependencies - Only needed at compile time
  • 🎯 Simple to Use - Just add one annotation to your interface
  • πŸ”Œ Highly Extensible - Based on Chain of Responsibility pattern
  • πŸ›  Type Safe - Generates type-safe Java code
  • πŸ“¦ Lightweight - No reflection, no runtime overhead

Quick Start

Prerequisites

  • Java 8 or above
  • Maven or Gradle build system

1. Add Dependencies

for maven project:

<dependencies>
    <!--
        the auto-pipeline annotation processor will generate
          the pipeline classes for the interface.
        annotation processor dependency should be "provided" scope,
          because it's only needed at compile time.
    -->
    <dependency>
        <groupId>com.foldright.auto-pipeline</groupId>
        <artifactId>auto-pipeline-processor</artifactId>
        <version>0.3.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

for gradle project:

/*
 * Gradle Kotlin DSL
 */
// the auto-pipeline annotation will be used in your interface type
compileOnly("com.foldright.auto-pipeline:auto-pipeline-annotations:0.3.0")
// the auto-pipeline annotation processor will generate the pipeline classes for the interface.
// use "annotationProcessor" scope because it's only needed at annotation processing time.
annotationProcessor("com.foldright.auto-pipeline:auto-pipeline-processor:0.3.0")

/*
 * Gradle Groovy DSL
 */
compileOnly 'com.foldright.auto-pipeline:auto-pipeline-annotations:0.3.0'
annotationProcessor 'com.foldright.auto-pipeline:auto-pipeline-processor:0.3.0'

auto-pipeline has published to maven central, click here to find the latest version.

2. Annotate Your Interface

Let's look at a simple example using a ConfigSource interface:

given an interface named ConfigSource, the ConfigSource has the get() method, input a string as key and output a string as the value. like this:

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

say, we want ConfigSource#get() has some extensibility, so we decide to apply the chain of responsibility pattern to it for extensibility.

Now it's auto-pipeline's turn to play a role, we simply add @AutoPipelin to ConfigSource:

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

auto-pipeline-processor will auto generate pipeline java files for ConfigSource into subpackage pipeline when compiled:

  • ConfigSourceHandler
    the responsibility interface we want to implement for extensibility
  • ConfigSourcePipeline
    the chain
  • ConfigSourceHandlerContext
  • AbstractConfigSourceHandlerContext
  • DefaultConfigSourceHandlerContext

3. Implement Handlers

We can implement handlers to add functionality to our pipeline:

public class MapConfigSourceHandler implements ConfigSourceHandler {
    private final Map<String, String> map;

    public MapConfigSourceHandler(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String get(String key, ConfigSourceHandlerContext context) {
        String value = map.get(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }
        return context.get(key);
    }
}

public class SystemConfigSourceHandler implements ConfigSourceHandler {
    public static final SystemConfigSourceHandler INSTANCE = new SystemConfigSourceHandler();

    @Override
    public String get(String key, ConfigSourceHandlerContext context) {
        String value = System.getProperty(key);
        if (StringUtils.isNotBlank(value)) {
            return value;
        }
        return context.get(key);
    }
}

4. Use the Pipeline

Create and use the pipeline by composing handlers:

Map<String, String> mapConfig = new HashMap<String, String>();
mapConfig.put("hello", "world");
ConfigSourceHandler mapConfigSourceHandler = new MapConfigSourceHandler(mapConfig);

ConfigSource pipeline = new ConfigSourcePipeline()
        .addLast(mapConfigSourceHandler)
        .addLast(SystemConfigSourceHandler.INSTANCE);

now, we can use the pipeline.get(...) to invoke the chain! πŸŽ‰

pipeline.get("hello");
// get value "world"
// from mapConfig / mapConfigSourceHandler

pipeline.get("java.specification.version")
// get value "1.8"
// from system properties / SystemConfigSourceHandler

check the runnable test case for details.

Documentation

For more detailed information and advanced usage, please check out the auto-pipeline documentation.

Examples

For more examples and use cases, check out our examples project and its test cases.

License

Apache License 2.0