Git Product home page Git Product logo

flapi's Introduction

Flapi - A fluent API generator for Java

v2.0 Build Status

What is it?

Flapi is a code generation library for creating fluent API's in Java. Fluent builders allow developers to more easily interact with your code, using a syntax more akin to natural language. See these articles for more information.

Flapi turns this:
Descriptor builder = Flapi.builder()
	.setPackage("unquietcode.tools.flapi.examples.email.builder")
	.setStartingMethodName("composeEmail")
	.setDescriptorName("Email")

	.addMethod("subject(String subject)").atMost(1)
	.addMethod("addRecipient(String emailAddress)").atLeast(1)
	.addMethod("sender(String emailAddress)").exactly(1)
	.addMethod("body(String text)").atMost(1)
	.addMethod("send()").last(EmailMessage.class)
.build();
...or this:
interface EmailHelper {

	@AtMost(1) void subject(String subject);
	@AtLeast(1) void addRecipient(String emailAddress);
	@Exactly(1) void sender(String emailAddress);
	@Any void addCC(String emailAddress);
	@Any void addBCC(String emailAddress);
	@AtMost(1) void body(String text);
	@Any void addAttachment(File file);
	@Last EmailMessage send();
}

Flapi.create(EmailHelper.class)
	.setPackage("unquietcode.tools.flapi.examples.email.builder")
	.setStartingMethodName("compose")
.build();
...into this:
composeEmail()
    .sender("[email protected]")
    .addRecipient("[email protected]")
    .subject("Just what do you think you're doing, Dave?")
    .body("I know that you and Frank were planning to disconnect me, " +
          "and I'm afraid that's something I cannot allow to happen...")
.send();

If you are using Maven (or Gradle, or Ivy) include the following dependency in your build script:

Maven

<dependency>
  <groupId>com.unquietcode.tools.flapi</groupId>
  <artifactId>flapi</artifactId>
  <version>2.0</version>
  <scope>test</scope>
</dependency>

Gradle

dependencies {
  testCompile 'com.unquietcode.tools.flapi:flapi:2.0'
}

In a test define your Descriptor object and output the generated source code. (The Pizza Builder example is a simple descriptor you can start with.) You can also make use of the Gradle plugin, or the Maven plugin, to perform the code generation.

Version 2.x of the project is built against JDK 8, while still exposing a JDK 7 compatible API, and using JDK 8 as the default target for code generation (selectable down to JDK 5). Version 1.x is built against JDK 7, and has a JDK 6 compatible API.

(PSA: If you are still using JDK 7 or lower, please do something about that soon.)

Additional Resources

  • Documentation
    Please visit the documentation page for a tour of Flapi's features and how to use them. (generated using the very nice tool docker)

  • Examples
    Many helpful examples are included on the wiki, corresponding to examples and tests in the src/test directory.

  • Upgrade Guide
    If you started using Flapi before version 1.0, check out this guide to see how to upgrade.

  • Blog Post
    The original blog post describing Flapi.

What's the project's status?

Version 1.0 and 2.0 have been released, marking a huge milestone in the stability of the code. If you started using Flapi before this version, check out the Upgrade Guide to see how to upgrade, since some deprecated features have been removed. See the Release Notes for the full release notes.

Going forward, the 1.x line will only receive important fixes and updates, with all new development firmly rooted in 2.x / JDK 8.

Problems?

Use the issue tracker to report problems encountered or new feature requests.

Contributing

Feel free to fork the project and fiddle around! Submit pull requests to improve the code.
Create issues to help support the project. Ask questions. (Say hello.)

Tip with Gratipay Tip with BitcoinBitcoin

If you like this software and find it useful, then please consider supporting my efforts through a donation via BitCoin or other means.

Special thanks to Concurrent, Inc. for their feedback and support as a user of Flapi, which they use in their Fluid library for Cascading.

License

Flapi is licensed under the Apache Software License (ASL) 2.0

Thanks!

Peace, love, and code.

flapi's People

Contributors

cwensel avatar unquietcode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flapi's Issues

FLAPI-179: Support array types.

Support the parsing of array types, such as int[] param and int param[].

Only single dimensions right now.

Changes to be made in MethodParser Flapi code and tests.


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-186: Create a Factory class.

It would be nice if there were some sort of class which provided the use of a static, no-arg method instead of the generator method which requires a helper.

Instead of passing in the helper implementation, Create a factory of some kind that takes another factory for the helpers. Then a new generator can be created on the fly. Then anyone can call the static method, though everything would have to be singletons then I guess.


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-118: Support method grouping for any() methods.

There is significant work required to support method grouping in any() methods, due to the fact that they are considered required and are part of the base class. This means that there must be some coordination between base classes and the states sitting on top of them, and in fact means that the method would not really be required.

Probably something like...method is required iff it is ungrouped or there is no matching group in the current block.


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-184: Upgrade to JDK 7.

Update the project to use JDK 7 as a baseline. As in, discontinue support for JDK6. This means:

  • JDK 7 features enabled by default
  • JDK 7 specified in the build
  • add JDK 8 to the travis build

Imported from JIRA
Originally reported by: UnquietCode

FLAPI-92: Investigate using the top level block recursively.

In FLAPI-79 it was pointed out that the top level block could conceivably be used recursively in a descriptor (through a block reference). Investigate this use case and see if it works and is useful.

If this case is determined to be unsupported, then maybe go back and redo FLAPI-79 as a new story.


Imported from JIRA
Originally reported by: UnquietCode

Gradle Plugin

Hey, was wondering if you had a gradle or ant plugin I'm missing or in the works?

ckw

FLAPI-48: Change 'once' to 'exactly'.

The semantics of once() are not that clear. The main goal is to avoid the use of between(x,x), so this will become exactly(x) and once() will go away in favor of simply atMost(1).


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-5: Write files to package folder.

Right now, the files are all written to some hardcoded folder, which doesn't even reflect the package selected. Update the code generator to write the files to the appropriate package for the descriptor, given a base folder.

The codemodel codewriter will automatically write the package folder hierarchy, it just needs a base folder.


Imported from JIRA
Originally reported by: UnquietCode

vargs in the signature can throw a NoSuchMethodException

given the generated method

void groupByMerge(Fields groupingFields, AtomicReference<GroupByMergeHelper> _helper1, Pipe... pipes);

The following exception will be thrown

java.lang.NoSuchMethodException: cascading.fluid.builder.ConcreteAssemblyHelper.groupByMerge(cascading.tuple.Fields, [Lcascading.pipe.Pipe;, java.util.concurrent.atomic.AtomicReference)
    at java.lang.Class.getMethod(Class.java:1624)
    at unquietcode.tools.flapi.runtime.BlockInvocationHandler.invokeAndReturn(BlockInvocationHandler.java:89)

FLAPI-189: Move issues from JIRA to GitHub

Using a script, move all of the issues from JIRA to GitHub. This seems like the thing to do.

As an added bonus, create a script which creates flat files out of the issues, in a generic format so that in the future they can be quickly loaded into whatever issue tracker is forced upon us next.


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-164: Gradle build plugin.

Equivalent plugin for gradle.

  • create new flapi-plugin module
  • move build plugin and friends to subfolder
    • parent can still be used to build maven plugin
  • new gradle plugin subfolder
  • build out the gradle plugin

Imported from JIRA
Originally reported by: UnquietCode

Maven repository is dead

Hi, the maven repository of the link http://www.unquietcode.com/maven/releases is not up anymore, could you re-up it / repair it?

It could be great also to deploy it on "classic" popular maven repositories. Your maven plugin is quite interesting, it would be great to make it easier to use it if it is deployed on a popular public mvn repo.

FLAPI-156: Make it possible to declare return types by string.

To support building the flapi descriptor without circular dependencies, make it possible to declare the return type of a last() method as a String. Internally the string is turned into a reference to the class.

{code:java}
// in the descriptor
.addMethod("last(String _class)").last()

// in use
.addMethod("myMethod()").last("String.class")
{code}

This will also affect the descriptor's return type.


Imported from JIRA
Originally reported by: UnquietCode

Support Bounded Generics in Methods

Trying to add a method that uses generics:

addMethod("withApplicationSettings(Class<? extends com.a.b.c.ApplicationSettings> settingsClass)")

Causes this exception:

Caused by: unquietcode.tools.flapi.MethodParser$ParseException: Expected to find character in {)} but was '?' (method signature is [ 'withApplicationSettings(Class<? extends com.paypal.creditpd.rappstack.server.flapi.application.RSApplicationSettings> settings)' ]).
    at unquietcode.tools.flapi.MethodParser.throwUnexpectedCharException(MethodParser.java:273)
    at unquietcode.tools.flapi.MethodParser.match(MethodParser.java:214)
    at unquietcode.tools.flapi.MethodParser.<init>(MethodParser.java:120)
    at unquietcode.tools.flapi.MethodParser.<init>(MethodParser.java:42)
    at unquietcode.tools.flapi.DescriptorPreValidator._checkForInvalidMethodSignatures(DescriptorPreValidator.java:119)

FLAPI-154: Add support for block mixins.

Continuing the 'overlays' idea, it would be nice if I could add an existing block as a 'mixin' to the current one. This would happen before validation, so all of the normal rules about method name collisions would apply.

A mixin is a list of zero or more block references which would be merged into the current block. The API might look like this:

// in descriptor
.addMethod("addMixin(String blockName)").any()

// in the builder
.addMixin(String blockName)

Imported from JIRA
Originally reported by: UnquietCode

FLAPI-7: Add javadocs.

Add at least to the public API. Try to add them to the internal classes to improve the overall understanding of the system.

...Yes, you can use regular comments form if you want for the internal stuff. :_


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-155: Support referencing the current block.

Make it possible to reference the current block, using a special constant like this. Ensure that the name is blocked from normal use!

This supports a few additional use cases:

  • access the descriptor block, without having to guess the block name
  • access an anonymous block recursively
  • decouples normal recursive calls from the block name

Imported from JIRA
Originally reported by: UnquietCode

FLAPI-167: Support default last methods.

Consider the following use case:
{code:java}
.addMethod("withStatusCode(int statusCode)").atMost(1)
.addMethod("withMessage(String message)").atMost(1)
.addMethod("withErrorCode(int errorCode)").exactly(1)
.addMethod("build()").last(ErrorResponse.class)
{code}

The last() method is really just optional in the case that we don't use all of the methods. However we want to implicitly call this method if we run out of other methods.

If I'm building up an object, but waiting to call the final method, then this would get in the way unless I disabled it. So at the least it should be disabled by default.

Create a feature which satisfies this:

  • when the feature is enabled for the block
  • when there is exactly one last method
  • and that method has zero parameters
  • then enable implicit terminals

Imported from JIRA
Originally reported by: UnquietCode

FLAPI-109: Allow users to disable the timestamp during file generation.

As a user, I would like to be able to disable the printing of timestamps in my generated files so that they will look identical to my source control unless they are really changed.

Requires that classes are generated the same way every time. SortedSet must be used everywhere, and also will need to ensure that the classes are generated by CodeModel the same way.


Imported from JIRA
Originally reported by: UnquietCode

FLAPI-191: Support @BlockChain parameters in any argument position.

Currently the runtime expects AtomicReference parameters to always be in the last position of the method. When coming from the annotation introspector however, the parameters could be in any position. It would be nice if the runtime could accommodate this, though it may require adding some additional information to the generated classes, which would be a breaking change.


Imported from JIRA
Originally reported by: UnquietCode

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.