diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..5697c0d
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,42 @@
+version: 2.1
+
+commands:
+ build_and_test:
+ parameters:
+ reports-dir:
+ type: string
+ default: "build/reports/test_results"
+ steps:
+ - checkout
+ - run:
+ name: Download dependencies
+ command: ./bld download
+ - run:
+ name: Compile source
+ command: ./bld compile
+ - run:
+ name: Run tests
+ command: ./bld jacoco -reports-dir=<< parameters.reports-dir >>
+ - store_test_results:
+ path: << parameters.reports-dir >>
+ - store_artifacts:
+ path: build/reports/jacoco/test/html
+
+jobs:
+ bld_jdk17:
+ docker:
+ - image: cimg/openjdk:17.0
+ steps:
+ - build_and_test
+
+ bld_jdk21:
+ docker:
+ - image: cimg/openjdk:21.0
+ steps:
+ - build_and_test
+
+workflows:
+ bld:
+ jobs:
+ - bld_jdk17
+ - bld_jdk21
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..1f808de
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,2 @@
+[*]
+insert_final_newline = true
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..6ec2ae2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# batch files are specific to windows and always crlf
+*.bat eol=crlf
diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml
new file mode 100644
index 0000000..64007ef
--- /dev/null
+++ b/.github/workflows/bld.yml
@@ -0,0 +1,76 @@
+name: bld-ci
+
+on: [push, pull_request, workflow_dispatch]
+
+jobs:
+ build-bld-project:
+ env:
+ COVERAGE_JDK: "17"
+
+ strategy:
+ matrix:
+ java-version: [17, 21, 24]
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
+
+ runs-on: ${{ matrix.os }}
+
+ steps:
+ - name: Checkout source repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up JDK ${{ matrix.java-version }}
+ uses: actions/setup-java@v4
+ with:
+ distribution: "zulu"
+ java-version: ${{ matrix.java-version }}
+
+ - name: Download dependencies [bld example]
+ working-directory: examples/java/bld
+ run: ./bld download
+
+ - name: Compile and run [bld example]
+ working-directory: examples/java/bld
+ run: |
+ ./bld compile
+ ./bld run
+ ./bld run-example
+
+ - name: Run example [gradle java examples]
+ working-directory: examples/java/gradle
+ run: |
+ ./gradlew run
+ ./gradlew runExample
+
+ - name: Run example [gradle kotlin examples]
+ working-directory: examples/kotlin
+ run: |
+ ./gradlew run
+ ./gradlew runExample
+
+ - name: Download dependencies
+ run: ./bld download
+
+ - name: Compile source
+ run: ./bld compile
+
+ - name: Run tests
+ run: ./bld jacoco
+
+ - name: Remove pom.xml
+ if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.os == 'ubuntu-latest'
+ run: rm -rf pom.xml
+
+ - name: SonarCloud Scan
+ uses: sonarsource/sonarcloud-github-action@master
+ if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.os == 'ubuntu-latest'
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ if: success() && matrix.java-version == env.COVERAGE_JDK && matrix.os == 'ubuntu-latest'
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.github_changelog_generator b/.github_changelog_generator
new file mode 100644
index 0000000..13dd68d
--- /dev/null
+++ b/.github_changelog_generator
@@ -0,0 +1 @@
+future-release=1.2.1
diff --git a/.gitignore b/.gitignore
index cb14895..dd3e0b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,25 +1,58 @@
-**/.idea/dictionaries
-**/.idea/gradle.xml
-**/.idea/libraries
-**/.idea/tasks.xml
-**/.idea/workspace.xml
-*.iws
-.DS_Store
-.classpath
.gradle
-.nb-gradle
-.project
-.settings
-/bin
-/build
-/deploy
-/dist
-/gen
-/gradle.properties
-/local.properties
-/out
-/proguard-project.txt
-/project.properties
-/test-output
-Thumbs.db
-ehthumbs.db
\ No newline at end of file
+.DS_Store
+build
+lib/bld/**
+!lib/bld/bld-wrapper.properties
+!lib/bld/bld-wrapper.jar
+lib/compile/
+lib/runtime/
+lib/standalone/
+lib/test/
+
+# IDEA ignores
+
+# User-specific
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+local.properties
+target
diff --git a/.idea/app.iml b/.idea/app.iml
new file mode 100644
index 0000000..6c0f6d7
--- /dev/null
+++ b/.idea/app.iml
@@ -0,0 +1,28 @@
+
+
An annotation processor that automatically generates a Version
class containing the semantic version (major, minor, patch, etc.) that is read from a Properties
file or defined in the annotation.
This processor was inspired by Cédric Beust's version-processor.
-@Version(major = 1, minor = 0, patch = 0, prerelease = "beta")
-public class A {
-// ...
@Version(properties = "version.properties")
-public class A {
-// ...
# version.properties
-version.major=1
-version.minor=0
-version.patch=0
-version.prerelease=beta
Upon running the annotator processor, a source file GeneratedVersion.java
is automatically generated with static methods to access the semantic version data. The source is based on a fully customizable Velocity template.
@Version(template = "myversion.vm")
-public class A {
-// ...
The default template implements the following static methods:
-Method | -Description | -Example | -
---|---|---|
getProject |
-The project name, if any. | -MyProject |
-
getBuildDate |
-The build date. | -java.util.Date |
-
getVersion |
-The full version string. | -1.0.0-alpha+001 |
-
getMajor |
-The major version. | -1 |
-
getMinor |
-The minor version. | -0 |
-
getPatch |
-The patch version. | -0 |
-
getPreRelease |
-The pre-release version, if any. | -alpha |
-
getBuildMetadata |
-The build metadata, if any. | -001 |
-
A very simple custom template might look something like:
-/* myversion.vm */
-package ${packageName}
-
-import java.util.Date;
-
-public final class ${className} {
- public final static String BUILDMETA = "${buildmeta}";
- public final static Date DATE = new Date(${epoch}L);
- public final static int MAJOR = ${major};
- public final static int MINOR = ${minor};
- public final static int PATCH = ${patch};
- public final static String PRERELEASE = "${prerelease}";
- public final static String PROJECT = "${project}";
-}
The Velocity variables are automatically filled in by the processor.
-The following annotation elements and properties are available:
-Element | -Property | -Description | -Default | -
---|---|---|---|
project |
-version.project |
-The project name. | -|
major |
-version.major |
-The major version number. | -1 |
-
minor |
-version.major |
-The minor version number. | -0 |
-
patch |
-version.patch |
-The patch version number. | -0 |
-
prerelease |
-version.prerelease |
-The pre-release version. | -|
buildmeta |
-version.buildmeta |
-The build metadata version. | -|
className |
-- | The name of the generated class. | -GeneratedVersion |
-
properties |
-- | The properties file. | -|
template |
-- | The template file. | -version.vm |
-
In order to easily incorporate with existing projects, the property keys may be assigned custom values:
-@Version(
- properties = "example.properties",
- majorKey = "example.major",
- minorKey = "example.minor",
- patchKey = "example.patch",
- prereleaseKey = "example.prerelease",
- buildmetaKey = "example.buildmeta",
- projectKey = "example.project"
-)
-public class Example {
-// ...
# example.properties
-example.project=Example
-example.major=1
-example.minor=0
-example.patch=0
-# ...
To install and run from Maven, configure an artifact as follows:
-<dependency>
- <groupId>net.thauvin.erik</groupId>
- <artifactId>semver</artifactId>
- <version>0.9.1-beta</version>
-</dependency>
To install and run from Gradle, add the following to the build.gradle
file:
dependencies {
- compile 'net.thauvin.erik:semver:0.9.1-beta'
-}
-The GeneratedVersion
class will be automatically generated in the build
directory upon compiling.
In order to also include the generated source code to your source tree, you should use the EWERK Annotation Processor Plugin. Start by addding the following to the very top of the build.gradle
file:
plugins {
- id "com.ewerk.gradle.plugins.annotation-processor" version "1.0.2"
-}
-Then add the following to the build.gradle
file:
dependencies {
- compile 'net.thauvin.erik:semver:0.9.1-beta'
-}
-
-annotationProcessor {
- project.version = getVersion(isRelease)
- library 'net.thauvin.erik:semver:0.9.1-beta'
- processor 'net.thauvin.erik.semver.VersionProcessor'
- // sourcesDir 'src/generated/java'
-}
-
-compileJava {
- // Disable the classpath procesor
- options.compilerArgs << '-proc:none'
-}
-The plugin implements a separate compile task that only runs the annotation processor and is executed during the build phase.
-Please look at the build.gradle
file in the example
module directory for a sample.
To install and run from Kobalt, add the following to the Build.kt
file:
dependencies {
- apt("net.thauvin.erik:semver:0.9.1-beta")
-}
-Incrementing the version is best left to your favorite build system.
-For a solution using Gradle, please have a look at the build.gradle
file in the example
module directory. To run the example with patch version auto-incrementing, issue the following command:
gradle clean release run
-
-
diff --git a/README.md b/README.md
index 94c69cc..cada04f 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,62 @@
-# Semantic Version Annotation Processor
+# Semantic Version Annotation Processor
-An [annotation processor](https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html) that automatically generates a `Version` class containing the [semantic version](http://semver.org/) (major, minor, patch, etc.) that is read from a `Properties` file or defined in the [annotation](https://docs.oracle.com/javase/tutorial/java/annotations/basics.html).
+[](https://opensource.org/licenses/BSD-3-Clause)
+[](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html)
+[](https://rife2.com/bld)
+[](https://github.com/ethauvin/semver/releases/latest)
+[](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/semver/)
+[](https://central.sonatype.com/artifact/net.thauvin.erik/semver)
-This processor was inspired by Cédric Beust's [version-processor](https://github.com/cbeust/version-processor).
+[](https://sonarcloud.io/dashboard?id=ethauvin_semver)
+[](https://github.com/ethauvin/semver/actions/workflows/bld.yml)
+[](https://ci.appveyor.com/project/ethauvin/semver)
+[](https://circleci.com/gh/ethauvin/semver/tree/master)
+
+An [annotation processor](https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html) that automatically generates a `GeneratedVersion` class based on a [Mustache](https://mustache.github.io/) template and containing the [semantic version](https://semver.org/) (major, minor, patch, etc.) that is read from a [Properties](https://docs.oracle.com/javase/tutorial/essential/environment/properties.html) file or defined in the [annotation](https://docs.oracle.com/javase/tutorial/java/annotations/basics.html).
+
+This processor was inspired by Cédric Beust's [version-processor](https://github.com/cbeust/version-processor) and works well in conjunction with the [__Semantic Version Plugin for Gradle__](https://github.com/ethauvin/semver-gradle).
+
+## Table of Contents
+
+- [Semantic Version Annotation Processor](#semantic-version-annotation-processor)
+ - [Table of Contents](#table-of-contents)
+ - [Examples](#examples)
+ - [Template](#template)
+ - [Default Template](#default-template)
+ - [Custom Template](#custom-template)
+ - [Elements \& Properties](#elements--properties)
+ - [Maven](#maven)
+ - [bld](#bld)
+ - [Gradle](#gradle)
+ - [Class Generation](#class-generation)
+ - [Class \& Source Generation](#class--source-generation)
+ - [Kotlin](#kotlin)
+ - [Kotlin \& Gradle](#kotlin--gradle)
+ - [Auto-Increment](#auto-increment)
+ - [Contributing](#contributing)
## Examples
-
-* Using annotation elements:
+
+- Using annotation elements:
```java
-@Version(major = 1, minor = 0, patch = 0, prerelease = "beta")
+import net.thauvin.erik.semver.Version;
+
+@Version(major = 2, minor = 1, patch = 1, preRelease = "beta")
public class A {
-// ...
+ // ...
+}
```
-* Or using a [properties](https://docs.oracle.com/javase/tutorial/essential/environment/properties.html) file:
+- Or using a [properties](hhttps://github.com/ethauvin/semver/blob/master/examples/java/version.properties) file:
```java
+import net.thauvin.erik.semver.Version;
+
@Version(properties = "version.properties")
public class A {
-// ...
+ // ...
+}
```
```ini
@@ -30,167 +67,267 @@ version.patch=0
version.prerelease=beta
```
+[View Examples](https://github.com/ethauvin/semver/tree/master/examples)
+
## Template
-Upon running the annotator processor, a source file `GeneratedVersion.java` is automatically generated with static methods to access the semantic version data. The source is based on a fully customizable [Velocity](http://velocity.apache.org/) template.
+Upon running the annotation processor, a source file [GeneratedVersion.java](https://github.com/ethauvin/semver/blob/master/examples/java/src/generated/java/com/example/GeneratedVersion.java) is automatically generated with static methods to access the semantic version data. The source is based on a fully customizable Mustache [template](https://github.com/ethauvin/semver/blob/master/src/main/resources/semver.mustache).
+
+To use your own template, simply create a `version.mustache` file in the project's root directory. The processor will automatically look for it.
+
+To specify your own template name, use:
```java
-@Version(template = "myversion.vm")
+@Version(template = "version.mustache")
public class A {
-// ...
+ // ...
+}
```
### Default Template
-The default template implements the following static methods:
+The [default template](https://github.com/ethauvin/semver/blob/master/src/main/resources/semver.mustache) implements the following static variables:
-Method | Description | Example
-------------------|----------------------------------|------------------
-`getProject` | The project name, if any. | `MyProject`
-`getBuildDate` | The build date. | [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html)
-`getVersion` | The full version string. | `1.0.0-alpha+001`
-`getMajor` | The major version. | `1`
-`getMinor` | The minor version. | `0`
-`getPatch` | The patch version. | `0`
-`getPreRelease` | The pre-release version, if any. | `alpha`
-`getBuildMetadata`| The build metadata, if any. | `001`
+| Field | Description | Example |
+|:-------------------|:---------------------------------|:----------------------------------------------------------------------------------|
+| `PROJECT` | The project name, if any. | `MyProject` |
+| `BUILDDATE` | The build date. | [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html) |
+| `VERSION` | The full version string. | `1.2.3-alpha+001` |
+| `MAJOR` | The major version. | `1` |
+| `MINOR` | The minor version. | `2` |
+| `PATCH` | The patch version. | `3` |
+| `PRERELEASE` | The pre-release version, if any. | `alpha` |
+| `PRERELASE_PREFIX` | The pre-release prefix | `-` |
+| `BUILDMETA` | The build metadata, if any. | `001` |
+| `BUILDMETA_PREFIX` | The metadata prefix. | `+` |
+| `SEPARATOR` | The version separator. | `.` |
### Custom Template
A very simple custom template might look something like:
```java
-/* myversion.vm */
-package ${packageName}
+/* version.mustache */
+package {{packageName}};
import java.util.Date;
-public final class ${className} {
- public final static String BUILDMETA = "${buildmeta}";
- public final static Date DATE = new Date(${epoch}L);
- public final static int MAJOR = ${major};
- public final static int MINOR = ${minor};
- public final static int PATCH = ${patch};
- public final static String PRERELEASE = "${prerelease}";
- public final static String PROJECT = "${project}";
+public final class {{className}} {
+ public final static String PROJECT = "{{project}}";
+ public final static Date DATE = new Date({{epoch}}L);
+ public final static String VERSION = "{{semver}}";
}
```
-The Velocity variables are automatically filled in by the processor.
-
+
+The mustache variables automatically filled in by the processor are:
+
+| Variable | Description | Type |
+|:------------------------------|:----------------------------|:---------|
+| `{{packageName}}` | The package name. | `String` |
+| `{{className}}` | The class name. | `String` |
+| `{{project}}` | The project name. | `String` |
+| `{{epoch}}` | The build epoch/unix time. | `long` |
+| `{{major}}` | The major version. | `int` |
+| `{{minor}}` | The minor version. | `int` |
+| `{{patch}}` | The patch version. | `int` |
+| `{{preRelease}}` | The pre-release version. | `String` |
+| `{{preReleasePrefix}}` | The pre-release prefix. | `String` |
+| `{{buildMeta}}` | The build metadata version. | `String` |
+| `{{buildMetaPrefix}}` | The metadata prefix. | `String` |
+| `{{separator}}` | The version separator. | `String` |
+| `{{semver}}` or `{{version}}` | The full semantic version. | `String` |
+
## Elements & Properties
The following annotation elements and properties are available:
-Element | Property | Description | Default
--------------|----------------------|----------------------------------|-------------
-`project` | `version.project` | The project name. |
-`major` | `version.major` | The major version number. | `1`
-`minor` | `version.major` | The minor version number. | `0`
-`patch` | `version.patch` | The patch version number. | `0`
-`prerelease` | `version.prerelease` | The pre-release version. |
-`buildmeta` | `version.buildmeta` | The build metadata version. |
-`className` | | The name of the generated class. | `GeneratedVersion`
-`properties` | | The properties file. |
-`template` | | The template file. | `version.vm`
+| Element | Property | Description | Default |
+|:-------------------|:----------------------------|:----------------------------------|:--------------------------|
+| `project` | `version.project` | The project name. | |
+| `major` | `version.major` | The major version number. | `1` |
+| `minor` | `version.major` | The minor version number. | `0` |
+| `patch` | `version.patch` | The patch version number. | `0` |
+| `preRelease` | `version.prerelease` | The pre-release version. | |
+| `preReleasePrefix` | `version.prerelease.prefix` | The pre-release prefix. | `-` |
+| `buildMeta` | `version.buildmeta` | The build metadata version. | |
+| `buildMetaPrefix` | `version.buildmeta.prefix` | The metadata prefix. | `+` |
+| `separator` | `version.separator` | The version separator. | `.` |
+| `packageName` | | The package name. | _Same as annotated class_ |
+| `className` | | The name of the generated class. | `GeneratedVersion` |
+| `properties` | | The properties file. | |
+| `template` | | The template file. | `version.mustache` |
+| `type` | | Either `java` or `kt` for Kotlin. | `java` |
+| `keysPrefix` | | The prefix for all property keys. | `version.` |
In order to easily incorporate with existing projects, the property keys may be assigned custom values:
```java
@Version(
- properties = "example.properties",
- majorKey = "example.major",
- minorKey = "example.minor",
- patchKey = "example.patch",
- prereleaseKey = "example.prerelease",
- buildmetaKey = "example.buildmeta",
- projectKey = "example.project"
+ properties = "example.properties",
+ keysPrefix = "example.",
+ majorKey = "maj",
+ minorKey = "min",
+ patchKey = "build",
+ preReleaseKey = "rel",
+ buildMetaKey = "meta",
+ projectKey = "project"
)
public class Example {
-// ...
+ // ...
+}
```
```ini
# example.properties
example.project=Example
-example.major=1
-example.minor=0
-example.patch=0
+example.maj=1
+example.min=0
+example.build=0
+example.rel=beta
+example.meta=
# ...
```
-## Usage with Maven, Grail and Kobalt
-### Maven
+> :warning: `keysPrefix` is a new element staring in `1.1.0` and may break older versions when using custom property keys.\
+> :zap: A quick fix is to include `keysPrefix=""` in the annotation to remove the default `version.` prefix.
-To install and run from [Maven](http://maven.apache.org/), configure an artifact as follows:
+## Maven
+
+To install and run from [Maven](https://maven.apache.org/), configure an artifact as follows:
```xml
GeneratedVersion
class containing the semantic
+version (major, minor, patch, etc.) that is read from a Properties file or defined in the annotation.
+
+@since 1.0
+
+
diff --git a/bin/main/semver-kt.mustache b/bin/main/semver-kt.mustache
new file mode 100644
index 0000000..0a58f86
--- /dev/null
+++ b/bin/main/semver-kt.mustache
@@ -0,0 +1,38 @@
+/*
+* This file is automatically generated.
+* Do not modify! -- ALL CHANGES WILL BE ERASED!
+*/
+
+package {{packageName}}
+
+import java.util.Date
+
+/**
+* Provides semantic version information.
+*
+* @author Semantic Version Annotation Processor
+*/
+object {{className}} {
+@JvmField
+val PROJECT = "{{project}}"
+@JvmField
+val BUILDDATE = Date({{epoch}}L)
+@JvmField
+val MAJOR = {{major}}
+@JvmField
+val MINOR = {{minor}}
+@JvmField
+val PATCH = {{patch}}
+@JvmField
+val PRERELEASE = "{{preRelease}}"
+@JvmField
+val PRERELEASE_PREFIX = "{{preReleasePrefix}}"
+@JvmField
+val BUILDMETA = "{{buildMeta}}"
+@JvmField
+val BUILDMEATA_PREFIX = "{{buildMetaPrefix}}"
+@JvmField
+val SEPARATOR = "{{separator}}"
+@JvmField
+val VERSION = "{{version}}"
+}
diff --git a/bin/main/semver.mustache b/bin/main/semver.mustache
new file mode 100644
index 0000000..cd7c567
--- /dev/null
+++ b/bin/main/semver.mustache
@@ -0,0 +1,34 @@
+/*
+* This file is automatically generated.
+* Do not modify! -- ALL CHANGES WILL BE ERASED!
+*/
+
+package {{packageName}};
+
+import java.util.Date;
+
+/**
+* Provides semantic version information.
+*
+* @author Semantic Version Annotation Processor
+*/
+public final class {{className}} {
+public static final String PROJECT = "{{project}}";
+public static final Date BUILDDATE = new Date({{epoch}}L);
+public static final int MAJOR = {{major}};
+public static final int MINOR = {{minor}};
+public static final int PATCH = {{patch}};
+public static final String PRERELEASE = "{{preRelease}}";
+public static final String PRERELEASE_PREFIX = "{{preReleasePrefix}}";
+public static final String BUILDMETA = "{{buildMeta}}";
+public static final String BUILDMETA_PREFIX = "{{buildMetaPrefix}}";
+public static final String SEPARATOR = "{{separator}}";
+public static final String VERSION = "{{version}}";
+
+/**
+* Disables the default constructor.
+*/
+private {{className}}() {
+throw new UnsupportedOperationException("Illegal constructor call.");
+}
+}
diff --git a/bin/test/net/thauvin/erik/semver/ConstantsTest.class b/bin/test/net/thauvin/erik/semver/ConstantsTest.class
new file mode 100644
index 0000000..934286a
Binary files /dev/null and b/bin/test/net/thauvin/erik/semver/ConstantsTest.class differ
diff --git a/bin/test/net/thauvin/erik/semver/VersionInfoTest.class b/bin/test/net/thauvin/erik/semver/VersionInfoTest.class
new file mode 100644
index 0000000..d6401b4
Binary files /dev/null and b/bin/test/net/thauvin/erik/semver/VersionInfoTest.class differ
diff --git a/bin/test/net/thauvin/erik/semver/VersionProcessorTest.class b/bin/test/net/thauvin/erik/semver/VersionProcessorTest.class
new file mode 100644
index 0000000..af2b771
Binary files /dev/null and b/bin/test/net/thauvin/erik/semver/VersionProcessorTest.class differ
diff --git a/bin/test/net/thauvin/erik/semver/VersionTest.class b/bin/test/net/thauvin/erik/semver/VersionTest.class
new file mode 100644
index 0000000..0047ff2
Binary files /dev/null and b/bin/test/net/thauvin/erik/semver/VersionTest.class differ
diff --git a/bld b/bld
new file mode 100755
index 0000000..824b742
--- /dev/null
+++ b/bld
@@ -0,0 +1,2 @@
+#!/usr/bin/env sh
+java -jar "$(dirname "$0")/lib/bld/bld-wrapper.jar" "$0" --build net.thauvin.erik.semver.SemverBuild "$@"
\ No newline at end of file
diff --git a/bld.bat b/bld.bat
new file mode 100644
index 0000000..ab43bcd
--- /dev/null
+++ b/bld.bat
@@ -0,0 +1,4 @@
+@echo off
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+java -jar "%DIRNAME%/lib/bld/bld-wrapper.jar" "%0" --build net.thauvin.erik.semver.SemverBuild %*
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index 93f8c9f..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,222 +0,0 @@
-plugins {
- id "com.jfrog.bintray" version "1.5"
-}
-apply plugin: 'java'
-apply plugin: 'idea'
-apply plugin: 'maven'
-apply plugin: 'maven-publish'
-
-import org.apache.tools.ant.taskdefs.condition.Os
-
-defaultTasks 'deploy'
-
-def getVersion(isIncrement = false)
-{
- def propsFile = 'version.properties'
- def majorKey = 'version.major'
- def minorKey = 'version.minor'
- def patchKey = 'version.patch'
- def metaKey = 'version.buildmeta'
- def preKey = 'version.prerelease'
- if (isIncrement)
- {
- ant.propertyfile(file: propsFile) {
- entry(key: patchKey,
- type: 'int',
- default: '-1',
- operation: '+')
- }
- }
- def p = new Properties()
- file(propsFile).withInputStream { stream -> p.load(stream) }
- def metadata = p.getProperty(metaKey, '')
- def prerelease = p.getProperty(preKey, '')
- return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') +
- (prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : ''))
-}
-
-version = getVersion()
-
-def deployDir = 'deploy'
-def isRelease = 'release' in gradle.startParameter.taskNames
-
-def mavenGroupId = 'net.thauvin.erik'
-def mavenName = 'SemVer'
-def mavenDescription = 'Semantic Version Annotation Processor'
-def mavenUrl = 'https://github.com/ethauvin/sermver'
-def mavenLicense = 'The BSD 3-Clause License'
-def mavenLicenseUrl = 'http://opensource.org/licenses/BSD-3-Clause'
-def mavenScmCon = 'https://github.com/ethauvin/semver.git'
-def mavenScmDevCon = 'git@github.com:ethauvin/semver.git'
-
-def pkgLicenses = ['BSD 3-Clause']
-def pkgIssueTrackerUrl = mavenUrl + '/issues'
-def pkgLabels = ['java', 'annotation', 'processor', 'semantic', 'version']
-
-[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
-
-repositories {
- mavenLocal()
- mavenCentral()
-}
-
-dependencies {
- compile 'org.apache.velocity:velocity:1.7'
- testCompile 'org.testng:testng:+'
-}
-
-bintray {
- user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
- key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY')
- publications = ['MyPublication']
- dryRun = false
- pkg {
- repo = 'maven'
- name = mavenName
- licenses = pkgLicenses
- desc = mavenDescription
- websiteUrl = mavenUrl
- issueTrackerUrl = pkgIssueTrackerUrl
- vcsUrl = mavenScmCon
- labels = pkgLabels
- publicDownloadNumbers = true
- version {
- name = project.version
- desc = 'Version ' + project.version
- vcsTag = project.version
- gpg {
- sign = true
- }
- }
- }
-}
-
-
-def pomConfig = {
- licenses {
- license {
- name mavenLicense
- url mavenLicenseUrl
- distribution 'repo'
- }
- }
- developers {
- developer {
- id 'ethauvin'
- name 'Erik C. Thauvin'
- email 'erik@thauvin.net'
- }
- }
- scm {
- connection 'scm:git:' + mavenScmCon
- developerConnection 'scm:git:' + mavenScmDevCon
- url mavenScmCon
- }
-}
-
-publishing {
- publications {
- MyPublication(MavenPublication) {
- from components.java
- artifact sourcesJar
- artifact javadocJar
- groupId mavenGroupId
- artifactId rootProject.name
- version project.version
-
- pom.withXml {
- def root = asNode()
- root.appendNode('name', mavenName)
- root.appendNode('description', mavenDescription)
- root.appendNode('url', mavenUrl)
- root.children().last() + pomConfig
- }
- }
- }
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc) {
- group = 'Build'
- description = 'Builds an archive of the javadoc docs.'
- classifier = 'javadoc'
- from javadoc.destinationDir
-}
-
-task sourcesJar(type: Jar) {
- group = 'Build'
- description = 'Builds an archive of the source code.'
- classifier = 'sources'
- from sourceSets.main.allSource
-}
-
-artifacts {
- archives javadocJar
- archives sourcesJar
-}
-
-javadoc {
- title = mavenDescription + ' ' + version
- options.tags = ['created']
- options.author = true
- options.addStringOption('link', 'http://docs.oracle.com/javase/8/docs/api/')
- options.addStringOption('sourcepath', project.hasProperty('jdkSrc') ? jdkSrc : "$System.env.JAVA_HOME/src.zip")
- if (JavaVersion.current().isJava8Compatible())
- {
- options.addStringOption('Xdoclint:none', '-quiet')
- }
-}
-
-test {
- useTestNG()
-}
-
-compileJava {
- doFirst {
- project.version = getVersion(isRelease)
- }
-}
-
-clean {
- delete deployDir
-}
-
-task copyToDeploy(type: Copy) {
- from jar
- into deployDir
-}
-
-task deploy(dependsOn: ['build', 'copyToDeploy']) {
- description = 'Copies all needed files to the ${deployDir} directory.'
- group = 'Publishing'
- outputs.dir deployDir
- inputs.files copyToDeploy
- mustRunAfter clean
-}
-
-task wrapper(type: Wrapper) {
- gradleVersion = gradle.gradleVersion
-}
-
-task release(dependsOn: ['deploy', 'wrapper']) << {
- group = 'Publishing'
- description = 'Releases new version.'
- isRelease = true
-}
-
-task pandoc(type: Exec) {
- group = 'Documentation'
- def pandoc_args = ['--from', 'markdown_github', '--to', 'html5', '-s', '-o', 'README.html', 'README.md']
- if (Os.isFamily(Os.FAMILY_WINDOWS))
- {
- commandLine(['cmd', '/c', 'pandoc'] + pandoc_args)
- }
- else
- {
- executable '/usr/local/bin/pandoc'
- args pandoc_args
- }
- standardOutput = new ByteArrayOutputStream()
- ext.output = {
- return standardOutput.toString()
- }
-}
\ No newline at end of file
diff --git a/config/pmd.xml b/config/pmd.xml
new file mode 100644
index 0000000..2641880
--- /dev/null
+++ b/config/pmd.xml
@@ -0,0 +1,109 @@
+
+An annotation
+processor that automatically generates a
+GeneratedVersion
class based on a Mustache template and containing
+the semantic version (major, minor,
+patch, etc.) that is read from a Properties
+file or defined in the annotation.
This processor was inspired by Cédric Beust's version-processor +and works well in conjunction with the Semantic +Version Plugin for Gradle.
+import net.thauvin.erik.semver.Version;
+
+@Version(major = 2, minor = 1, patch = 1, preRelease = "beta")
+public class A {
+// ...
+ }
import net.thauvin.erik.semver.Version;
+
+@Version(properties = "version.properties")
+public class A {
+// ...
+ }
# version.properties
+version.major=1
+version.minor=0
+version.patch=0
+version.prerelease=beta
Upon running the annotation processor, a source file GeneratedVersion.java +is automatically generated with static methods to access the semantic +version data. The source is based on a fully customizable Mustache template.
+To use your own template, simply create a
+version.mustache
file in the project's root directory. The
+processor will automatically look for it.
To specify your own template name, use:
+@Version(template = "version.mustache")
+public class A {
+// ...
+ }
The default +template implements the following static variables:
+Field | +Description | +Example | +
---|---|---|
PROJECT |
+The project name, if any. | +MyProject |
+
BUILDDATE |
+The build date. | +java.util.Date |
+
VERSION |
+The full version string. | +1.2.3-alpha+001 |
+
MAJOR |
+The major version. | +1 |
+
MINOR |
+The minor version. | +2 |
+
PATCH |
+The patch version. | +3 |
+
PRERELEASE |
+The pre-release version, if any. | +alpha |
+
PRERELASE_PREFIX |
+The pre-release prefix | +- |
+
BUILDMETA |
+The build metadata, if any. | +001 |
+
BUILDMETA_PREFIX |
+The metadata prefix. | ++ |
+
SEPARATOR |
+The version separator. | +. |
+
A very simple custom template might look something like:
+/* version.mustache */
+package {{packageName}};
+
+import java.util.Date;
+
+public final class {{className}} {
+public final static String PROJECT = "{{project}}";
+ public final static Date DATE = new Date({{epoch}}L);
+ public final static String VERSION = "{{semver}}";
+ }
The mustache variables automatically filled in by the processor +are:
+Variable | +Description | +Type | +
---|---|---|
{{packageName}} |
+The package name. | +String |
+
{{className}} |
+The class name. | +String |
+
{{project}} |
+The project name. | +String |
+
{{epoch}} |
+The build epoch/unix time. | +long |
+
{{major}} |
+The major version. | +int |
+
{{minor}} |
+The minor version. | +int |
+
{{patch}} |
+The patch version. | +int |
+
{{preRelease}} |
+The pre-release version. | +String |
+
{{preReleasePrefix}} |
+The pre-release prefix. | +String |
+
{{buildMeta}} |
+The build metadata version. | +String |
+
{{buildMetaPrefix}} |
+The metadata prefix. | +String |
+
{{separator}} |
+The version separator. | +String |
+
{{semver}} or
+{{version}} |
+The full semantic version. | +String |
+
The following annotation elements and properties are available:
+Element | +Property | +Description | +Default | +
---|---|---|---|
project |
+version.project |
+The project name. | ++ |
major |
+version.major |
+The major version number. | +1 |
+
minor |
+version.major |
+The minor version number. | +0 |
+
patch |
+version.patch |
+The patch version number. | +0 |
+
preRelease |
+version.prerelease |
+The pre-release version. | ++ |
preReleasePrefix |
+version.prerelease.prefix |
+The pre-release prefix. | +- |
+
buildMeta |
+version.buildmeta |
+The build metadata version. | ++ |
buildMetaPrefix |
+version.buildmeta.prefix |
+The metadata prefix. | ++ |
+
separator |
+version.separator |
+The version separator. | +. |
+
packageName |
++ | The package name. | +Same as annotated class | +
className |
++ | The name of the generated class. | +GeneratedVersion |
+
properties |
++ | The properties file. | ++ |
template |
++ | The template file. | +version.mustache |
+
type |
++ | Either java or
+kt for Kotlin. |
+java |
+
keysPrefix |
++ | The prefix for all property keys. | +version. |
+
In order to easily incorporate with existing projects, the property +keys may be assigned custom values:
+@Version(
+= "example.properties",
+ properties = "example.",
+ keysPrefix = "maj",
+ majorKey = "min",
+ minorKey = "build",
+ patchKey = "rel",
+ preReleaseKey = "meta",
+ buildMetaKey = "project"
+ projectKey )
+public class Example {
+// ...
+ }
# example.properties
+example.project=Example
+example.maj=1
+example.min=0
+example.build=0
+example.rel=beta
+example.meta=
+# ...
++⚠️ +
+keysPrefix
is a new element staring in1.1.0
+and may break older versions when using custom property keys.
+⚡ A quick fix is to include +keysPrefix=""
in the annotation to remove the default +version.
prefix.
To install and run from Maven, configure an artifact as +follows:
+dependency>
+ <groupId>net.thauvin.erik</groupId>
+ <artifactId>semver</artifactId>
+ <version>1.2.1</version>
+ <dependency> </
Please look at pom.xml +in the examples/java +directory for a sample:
+mvn verify
To install and run from bld, just +add the dependency to your build file:
+public class ExampleBuild extends Project {
+public ExampleBuild() {
+ // ...
+ scope(compile)
+ .include(dependency("net.thauvin.erik", "semver", version(1, 2, 1)));
+ }
+ }
Please look at ExampleBuild
+in the examples/java/bld
+directory for a sample. It also shows how to incorporate the generated
+code into the source tree
, more information is also
+available here.
bld also has a Generated +Version extension which provides similar functionalities.
+To install and run from Gradle, add +the following to build.gradle:
+{
+ repositories mavenCentral()
+ }
+
+{
+ dependencies 'net.thauvin.erik:semver:1.2.1'
+ annotationProcessor 'net.thauvin.erik:semver:1.2.1'
+ compileOnly }
+
+.withType(JavaCompile).configureEach {
+ tasks.compilerArgs += [ "-Asemver.project.dir=$projectDir" ]
+ options}
The directory containing the configuration files
+(version.properties
, version.mustache
) must be
+specified using the semver.project.dir
processor
+argument.
The GeneratedVersion.java
+class will be automatically created in the build/generated
+directory upon compiling.
Please look at build.gradle +in the examples/java/gradle +directory for a sample.
+In order to also incorporate the generated source code into the
+source tree
, add the following to build.gradle:
.withType(JavaCompile).configureEach {
+ tasks.generatedSourceOutputDirectory.set(file("${projectDir}/src/generated/java"))
+ options}
The GeneratedVersion.java
+file will now be located in src/generated
.
The annotation processor also supports Kotlin.
+To generate a Kotlin version file, simply specify the
+type
as follows:
import net.thauvin.erik.semver.Version
+
+@Version(properties = "version.properties", type="kt")
+open class Main {
+// ...
+ }
The Kotlin +default template implements the same static fields and functions as +the Java template.
+Please look at the examples/kotlin +project for a build.gradle.kts +sample.
+To install and run from Gradle, add +the following to build.gradle.kts:
+var semverProcessor = "net.thauvin.erik:semver:1.2.1"
+
+{
+ dependencies (semverProcessor)
+ kapt(semverProcessor)
+ compileOnly}
+
+{
+ kapt {
+ arguments ("semver.project.dir", projectDir)
+ arg}
+ }
The directory containing the configuration files
+(version.properties
, version.mustache
) must be
+specified using the semver.project.dir
processor
+argument.
Incrementing the version is best left to your favorite build system. +For a solution using Gradle, please have a look at the Semver Version +Plugin for Gradle.
+There are also full examples +in both Java +and Kotlin +showing how to use both the plugin and annotation processor +concurrently.
+If you want to contribute to this project, all you have to do is +clone the GitHub repository:
+git clone git@github.com:ethauvin/semver.git
+Then use bld to build:
+cd semver
+./bld compile
+The project has an IntelliJ +IDEA project structure. You can just open it after all the +dependencies were downloaded and peruse the code.
+ + diff --git a/docs/github-pandoc.css b/docs/github-pandoc.css new file mode 100644 index 0000000..d7edd25 --- /dev/null +++ b/docs/github-pandoc.css @@ -0,0 +1,425 @@ +/* github-pandoc.css found at https://gist.github.com/dashed/6714393 */ +/*! normalize.css v2.1.3 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined in IE 8/9. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/** + * Correct `inline-block` display not defined in IE 8/9. + */ + +audio, +canvas, +video { + display: inline-block; +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9. + * Hide the `template` element in IE, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background: transparent; +} + +/** + * Address `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari 5, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Correct font family set oddly in Safari 5 and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +/** + * Improve readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre-wrap; +} + +/** + * Set consistent quote types. + */ + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9. + */ + +img { + border: 0; +} + +/** + * Correct overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari 5. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * 1. Correct font family not being inherited in all browsers. + * 2. Correct font size not being inherited in all browsers. + * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. + */ + +button, +input, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. + * Correct `select` style inheritance in Firefox 4+ and Opera. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * 1. Remove default vertical scrollbar in IE 8/9. + * 2. Improve readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +.go-top { +position: fixed; +bottom: 2em; +right: 2em; +text-decoration: none; +background-color: #E0E0E0; +font-size: 12px; +padding: 1em; +display: inline; +} + +/* Github css */ + +html,body{ margin: auto; + padding-right: 1em; + padding-left: 1em; + max-width: 44em; color:black;}*:not('#mkdbuttons'){margin:0;padding:0}body{font:13.34px helvetica,arial,freesans,clean,sans-serif;-webkit-font-smoothing:subpixel-antialiased;line-height:1.4;padding:3px;background:#fff;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px}p{margin:1em 0}a{color:#4183c4;text-decoration:none}body{background-color:#fff;padding:30px;margin:15px;font-size:14px;line-height:1.6}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}@media screen{body{box-shadow:0 0 0 1px #cacaca,0 0 0 4px #eee}}h1,h2,h3,h4,h5,h6{margin:20px 0 10px;padding:0;font-weight:bold;-webkit-font-smoothing:subpixel-antialiased;cursor:text}h1{font-size:28px;color:#000}h2{font-size:24px;border-bottom:1px solid #ccc;color:#000}h3{font-size:18px;color:#333}h4{font-size:16px;color:#333}h5{font-size:14px;color:#333}h6{color:#777;font-size:14px}p,blockquote,table,pre{margin:15px 0}ul{padding-left:30px}ol{padding-left:30px}ol li ul:first-of-type{margin-top:0}hr{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;border:0 none;color:#ccc;height:4px;padding:0}body>h2:first-child{margin-top:0;padding-top:0}body>h1:first-child{margin-top:0;padding-top:0}body>h1:first-child+h2{margin-top:0;padding-top:0}body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child{margin-top:0;padding-top:0}a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6{margin-top:0;padding-top:0}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p,ul li>:first-child,ol li>:first-child{margin-top:0}dl{padding:0}dl dt{font-size:14px;font-weight:bold;font-style:italic;padding:0;margin:15px 0 5px}dl dt:first-child{padding:0}dl dt>:first-child{margin-top:0}dl dt>:last-child{margin-bottom:0}dl dd{margin:0 0 15px;padding:0 15px}dl dd>:first-child{margin-top:0}dl dd>:last-child{margin-bottom:0}blockquote{border-left:4px solid #DDD;padding:0 15px;color:#777}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}table{border-collapse:collapse;border-spacing:0;font-size:100%;font:inherit}table th{font-weight:bold;border:1px solid #ccc;padding:6px 13px}table td{border:1px solid #ccc;padding:6px 13px}table tr{border-top:1px solid #ccc;background-color:#fff}table tr:nth-child(2n){background-color:#f8f8f8}img{max-width:100%}code,tt{margin:0 2px;padding:0 5px;white-space:nowrap;border:1px solid #eaeaea;background-color:#f8f8f8;border-radius:3px;font-family:Consolas,'Liberation Mono',Courier,monospace;font-size:12px;color:#333}pre>code{margin:0;padding:0;white-space:pre;border:0;background:transparent}.highlight pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre{background-color:#f8f8f8;border:1px solid #ccc;font-size:13px;line-height:19px;overflow:auto;padding:6px 10px;border-radius:3px}pre code,pre tt{background-color:transparent;border:0}.poetry pre{font-family:Georgia,Garamond,serif!important;font-style:italic;font-size:110%!important;line-height:1.6em;display:block;margin-left:1em}.poetry pre code{font-family:Georgia,Garamond,serif!important;word-break:break-all;word-break:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;hyphens:auto;white-space:pre-wrap}sup,sub,a.footnote{font-size:1.4ex;height:0;line-height:1;vertical-align:super;position:relative}sub{vertical-align:sub;top:-1px}@media print{body{background:#fff}img,pre,blockquote,table,figure{page-break-inside:avoid}body{background:#fff;border:0}code{background-color:#fff;color:#333!important;padding:0 .2em;border:1px solid #dedede}pre{background:#fff}pre code{background-color:white!important;overflow:visible}}@media screen{body.inverted{color:#eee!important;border-color:#555;box-shadow:none}.inverted body,.inverted hr .inverted p,.inverted td,.inverted li,.inverted h1,.inverted h2,.inverted h3,.inverted h4,.inverted h5,.inverted h6,.inverted th,.inverted .math,.inverted caption,.inverted dd,.inverted dt,.inverted blockquote{color:#eee!important;border-color:#555;box-shadow:none}.inverted td,.inverted th{background:#333}.inverted h2{border-color:#555}.inverted hr{border-color:#777;border-width:1px!important}::selection{background:rgba(157,193,200,0.5)}h1::selection{background-color:rgba(45,156,208,0.3)}h2::selection{background-color:rgba(90,182,224,0.3)}h3::selection,h4::selection,h5::selection,h6::selection,li::selection,ol::selection{background-color:rgba(133,201,232,0.3)}code::selection{background-color:rgba(0,0,0,0.7);color:#eee}code span::selection{background-color:rgba(0,0,0,0.7)!important;color:#eee!important}a::selection{background-color:rgba(255,230,102,0.2)}.inverted a::selection{background-color:rgba(255,230,102,0.6)}td::selection,th::selection,caption::selection{background-color:rgba(180,237,95,0.5)}.inverted{background:#0b2531;background:#252a2a}.inverted body{background:#252a2a}.inverted a{color:#acd1d5}}.highlight .c{color:#998;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .k,.highlight .o{font-weight:bold}.highlight .cm{color:#998;font-style:italic}.highlight .cp{color:#999;font-weight:bold}.highlight .c1{color:#998;font-style:italic}.highlight .cs{color:#999;font-weight:bold;font-style:italic}.highlight .gd{color:#000;background-color:#fdd}.highlight .gd .x{color:#000;background-color:#faa}.highlight .ge{font-style:italic}.highlight .gr{color:#a00}.highlight .gh{color:#999}.highlight .gi{color:#000;background-color:#dfd}.highlight .gi .x{color:#000;background-color:#afa}.highlight .go{color:#888}.highlight .gp{color:#555}.highlight .gs{font-weight:bold}.highlight .gu{color:#800080;font-weight:bold}.highlight .gt{color:#a00}.highlight .kc,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr{font-weight:bold}.highlight .kt{color:#458;font-weight:bold}.highlight .m{color:#099}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .nb{color:#0086b3}.highlight .nc{color:#458;font-weight:bold}.highlight .no{color:#008080}.highlight .ni{color:#800080}.highlight .ne,.highlight .nf{color:#900;font-weight:bold}.highlight .nn{color:#555}.highlight .nt{color:#000080}.highlight .nv{color:#008080}.highlight .ow{font-weight:bold}.highlight .w{color:#bbb}.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:#099}.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .se,.highlight .sh,.highlight .si,.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .bp{color:#999}.highlight .vc,.highlight .vg,.highlight .vi{color:#008080}.highlight .il{color:#099}.highlight .gc{color:#999;background-color:#eaf2f5}.type-csharp .highlight .k,.type-csharp .highlight .kt{color:#00F}.type-csharp .highlight .nf{color:#000;font-weight:normal}.type-csharp .highlight .nc{color:#2b91af}.type-csharp .highlight .nn{color:#000}.type-csharp .highlight .s,.type-csharp .highlight .sc{color:#a31515} diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index d7290a0..0000000 --- a/example/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -**/.idea/dictionaries -**/.idea/gradle.xml -**/.idea/libraries -**/.idea/tasks.xml -**/.idea/workspace.xml -*.iws -.DS_Store -.classpath -.gradle -.nb-gradle -.project -.settings -/bin -/build -/deploy -/dist -/gen -/local.properties -/out -/proguard-project.txt -/project.properties -/test-output -Thumbs.db -ehthumbs.db \ No newline at end of file diff --git a/example/build.gradle b/example/build.gradle deleted file mode 100644 index f252bac..0000000 --- a/example/build.gradle +++ /dev/null @@ -1,94 +0,0 @@ -plugins { - id "com.ewerk.gradle.plugins.annotation-processor" version "1.0.2" -} -apply plugin: 'java' -apply plugin: 'idea' -apply plugin: 'application' - -defaultTasks 'run' - -def isRelease = 'release' in gradle.startParameter.taskNames -def deployDir = 'deploy' - -def getVersion(isIncrement = false) -{ - def propsFile = 'version.properties' - def majorKey = 'version.major' - def minorKey = 'version.minor' - def patchKey = 'version.patch' - def metaKey = 'version.buildmeta' - def preKey = 'version.prerelease' - if (isIncrement) - { - ant.propertyfile(file: propsFile) { - entry(key: patchKey, - type: 'int', - default: '-1', - operation: '+') - } - } - def p = new Properties() - file(propsFile).withInputStream { stream -> p.load(stream) } - def metadata = p.getProperty(metaKey, '') - def prerelease = p.getProperty(preKey, '') - return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') + - (prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : '')) -} - -version = getVersion() - -mainClassName = 'net.thauvin.erik.semver.example.Example' -[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' - -repositories { - mavenLocal() - mavenCentral() -} - -dependencies { - compile 'net.thauvin.erik:semver:+' -} - -annotationProcessor { - project.version = getVersion(isRelease) - library 'net.thauvin.erik:semver:0.9.1-beta' - processor 'net.thauvin.erik.semver.VersionProcessor' -} - -compileJava { - options.compilerArgs << '-proc:none' -} - -jar { - manifest.attributes('Main-Class': mainClassName) -} - -clean { - delete deployDir -} - - -task copyToDeploy(type: Copy) { - from jar - into deployDir -} - -task deploy(dependsOn: ['build', 'copyToDeploy']) { - description = 'Copies all needed files to the ${deployDir} directory.' - group = 'Publishing' - outputs.dir deployDir - inputs.files copyToDeploy - mustRunAfter clean -} - - -task release(dependsOn: ['deploy', 'wrapper']) << { - group = 'Publishing' - description = 'Releases new version.' - isRelease = true -} - -task wrapper(type: Wrapper) { - gradleVersion = gradle.gradleVersion -} - diff --git a/example/example.iml b/example/example.iml deleted file mode 100644 index 2a1096e..0000000 --- a/example/example.iml +++ /dev/null @@ -1,229 +0,0 @@ - -
+ * To incorporate the generated source code into the source tree, add this directory as an additional source
+ * location in your IDE.
+ */
+ @Override
+ public void compile() throws Exception {
+ var generated = new File(buildDirectory(), "generated");
+ var ignore = generated.mkdir();
+ compileOperation().compileOptions().process(Processing.FULL).sourceOutput(generated);
+ super.compile();
+ }
+
+ @BuildCommand(value = "run-example", summary = "Runs the example")
+ public void runExample() throws Exception {
+ runOperation().fromProject(this).mainClass("com.example.Example").execute();
+ }
+}
diff --git a/examples/java/bld/src/main/java/com/example/App.java b/examples/java/bld/src/main/java/com/example/App.java
new file mode 100644
index 0000000..91134b7
--- /dev/null
+++ b/examples/java/bld/src/main/java/com/example/App.java
@@ -0,0 +1,31 @@
+package com.example;
+
+import net.thauvin.erik.semver.Version;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+@Version(properties = "version.properties")
+public final class App {
+ /**
+ * Command line interface.
+ *
+ * @param args The command line parameters.
+ */
+ public static void main(final String... args) {
+ final var sdf = new SimpleDateFormat("EEE, d MMM yyyy 'at' HH:mm:ss z", Locale.US);
+
+ System.out.println("-----------------------------------------------------");
+
+ System.out.println(" Version: " + GeneratedVersion.PROJECT + ' ' + GeneratedVersion.VERSION);
+
+ System.out.println(" Built on: " + sdf.format(GeneratedVersion.BUILDDATE));
+ System.out.println(" Major: " + GeneratedVersion.MAJOR);
+ System.out.println(" Minor: " + GeneratedVersion.MINOR);
+ System.out.println(" Patch: " + GeneratedVersion.PATCH);
+ System.out.println(" PreRelease: " + GeneratedVersion.PRERELEASE);
+ System.out.println(" BuildMetaData: " + GeneratedVersion.BUILDMETA);
+
+ System.out.println("-----------------------------------------------------");
+ }
+}
diff --git a/examples/java/bld/src/main/java/com/example/Example.java b/examples/java/bld/src/main/java/com/example/Example.java
new file mode 100644
index 0000000..1829d52
--- /dev/null
+++ b/examples/java/bld/src/main/java/com/example/Example.java
@@ -0,0 +1,21 @@
+package com.example;
+
+import net.thauvin.erik.semver.Version;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+@Version(properties = "example.properties", template = "example.mustache", className = "ExampleVersion",
+ keysPrefix = "example.")
+public class Example {
+ public static void main(final String... args) {
+ final var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
+
+ System.out.println("-- From Example -------------------------------------");
+
+ System.out.println(" " + ExampleVersion.PROJECT + ' ' + ExampleVersion.VERSION
+ + " (" + sdf.format(ExampleVersion.BUILDDATE) + ')');
+
+ System.out.println("-----------------------------------------------------");
+ }
+}
diff --git a/examples/java/bld/src/test/java/com/example/ExampleTest.java b/examples/java/bld/src/test/java/com/example/ExampleTest.java
new file mode 100644
index 0000000..f0452f2
--- /dev/null
+++ b/examples/java/bld/src/test/java/com/example/ExampleTest.java
@@ -0,0 +1,18 @@
+package com.example;
+
+public class ExampleTest {
+ private static final String HELLO = "Hello!";
+
+ public static void main(String[] args) {
+ var hello = new ExampleTest().verifyHello();
+ if (HELLO.equals(hello)) {
+ System.out.println("Succeeded");
+ } else {
+ throw new AssertionError();
+ }
+ }
+
+ String verifyHello() {
+ return HELLO;
+ }
+}
diff --git a/examples/java/bld/version.properties b/examples/java/bld/version.properties
new file mode 100644
index 0000000..dc68bf3
--- /dev/null
+++ b/examples/java/bld/version.properties
@@ -0,0 +1,9 @@
+#Generated by the Semver Plugin for Gradle
+#Sat Apr 27 17:05:34 PDT 2019
+version.buildmeta=007
+version.major=11
+version.minor=11
+version.patch=20
+version.prerelease=beta
+version.project=Java App
+version.semver=11.11.20-beta+007
diff --git a/examples/java/gradle/.editorconfig b/examples/java/gradle/.editorconfig
new file mode 100644
index 0000000..1f808de
--- /dev/null
+++ b/examples/java/gradle/.editorconfig
@@ -0,0 +1,2 @@
+[*]
+insert_final_newline = true
diff --git a/examples/java/gradle/.gitattributes b/examples/java/gradle/.gitattributes
new file mode 100644
index 0000000..6ec2ae2
--- /dev/null
+++ b/examples/java/gradle/.gitattributes
@@ -0,0 +1,5 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# batch files are specific to windows and always crlf
+*.bat eol=crlf
diff --git a/examples/java/gradle/.gitignore b/examples/java/gradle/.gitignore
new file mode 100644
index 0000000..a78c5c2
--- /dev/null
+++ b/examples/java/gradle/.gitignore
@@ -0,0 +1,82 @@
+!.vscode/extensions.json
+!.vscode/launch.json
+!.vscode/settings.json
+!.vscode/tasks.json
+!gradle-wrapper.jar
+.classpath
+.DS_Store
+.gradle
+.history
+.idea_modules/
+.idea/**/contentModel.xml
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/dataSources/
+.idea/**/dbnavigator.xml
+.idea/**/dictionaries
+.idea/**/dynamic.xml
+.idea/**/gradle.xml
+.idea/**/libraries
+.idea/**/mongoSettings.xml
+.idea/**/shelf
+.idea/**/sqlDataSources.xml
+.idea/**/tasks.xml
+.idea/**/uiDesigner.xml
+.idea/**/usage.statistics.xml
+.idea/**/workspace.xml
+.idea/caches/build_file_checksums.ser
+.idea/httpRequests
+.idea/replstate.xml
+.kobalt
+.mtj.tmp/
+.mvn/timing.properties
+.mvn/wrapper/maven-wrapper.jar
+.nb-gradle
+.project
+.scannerwork
+.settings
+.vscode/*
+*.class
+*.code-workspace
+*.ctxt
+*.ear
+*.iws
+*.jar
+*.log
+*.nar
+*.rar
+*.sublime-*
+*.tar.gz
+*.war
+*.zip
+atlassian-ide-plugin.xml
+bin/
+build/
+cmake-build-*/
+com_crashlytics_export_strings.xml
+crashlytics-build.properties
+crashlytics.properties
+dependency-reduced-pom.xml
+deploy/
+dist/
+ehthumbs.db
+fabric.properties
+gen/
+gradle.properties
+hs_err_pid*
+kobaltBuild
+kobaltw*-test
+lib/kotlin*
+libs/
+local.properties
+out/
+pom.xml.next
+pom.xml.releaseBackup
+pom.xml.tag
+pom.xml.versionsBackup
+proguard-project.txt
+project.properties
+release.properties
+target/
+test-output
+Thumbs.db
diff --git a/examples/java/gradle/.idea/.name b/examples/java/gradle/.idea/.name
new file mode 100644
index 0000000..2ba6afe
--- /dev/null
+++ b/examples/java/gradle/.idea/.name
@@ -0,0 +1 @@
+semver-examples-java-gradle
\ No newline at end of file
diff --git a/examples/java/gradle/.idea/compiler.xml b/examples/java/gradle/.idea/compiler.xml
new file mode 100644
index 0000000..a83902e
--- /dev/null
+++ b/examples/java/gradle/.idea/compiler.xml
@@ -0,0 +1,20 @@
+
+ Formatted as:
+ * For example:
+ *
- * Formatted as:
- *
- * For example:
- * Constants
class holds the constant variables used throughout this project.
*
- * @author Erik C. Thauvin
+ * @author Erik C. Thauvin
* @created 2016-01-13
* @since 1.0
*/
-public final class Constants
-{
- /**
- * The default class name.
- */
- public static final String DEFAULT_CLASS_NAME = "GeneratedVersion";
+@SuppressWarnings("PMD.DataClass")
+public final class Constants {
+ /**
+ * The default metadata prefix.
+ */
+ public static final String DEFAULT_BUILDMETA_PREFIX = "+";
+ /**
+ * The default class name.
+ */
+ public static final String DEFAULT_CLASS_NAME = "GeneratedVersion";
+ /**
+ * The default Java mustache template.
+ */
+ public static final String DEFAULT_JAVA_TEMPLATE = "semver.mustache";
+ /**
+ * The default java type.
+ **/
+ public static final String DEFAULT_JAVA_TYPE = "java";
+ /**
+ * The default keys prefix.
+ */
+ public static final String DEFAULT_KEYS_PREFIX = "version.";
+ /**
+ * The default Kotlin mustache template.
+ */
+ public static final String DEFAULT_KOTLIN_TEMPLATE = "semver-kt.mustache";
+ /**
+ * The default major version.
+ */
+ public static final int DEFAULT_MAJOR = 1;
+ /**
+ * The default minor version.
+ */
+ public static final int DEFAULT_MINOR = 0;
+ /**
+ * The default patch version.
+ */
+ public static final int DEFAULT_PATCH = 0;
+ /**
+ * The default prerelease prefix.
+ */
+ public static final String DEFAULT_PRERELEASE_PREFIX = "-";
+ /**
+ * The default version separator.
+ */
+ public static final String DEFAULT_SEPARATOR = ".";
+ /**
+ * The default mustache template.
+ */
+ public static final String DEFAULT_TEMPLATE_NAME = "version.mustache";
+ /**
+ * The empty string.
+ */
+ public static final String EMPTY = "";
+ /**
+ * The generated source files directory kotlin option.
+ */
+ public static final String KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated";
+ /**
+ * The build metadata property key.
+ */
+ public static final String KEY_VERSION_BUILDMETA = "buildmeta";
+ /**
+ * The build metadata prefix property key.
+ */
+ public static final String KEY_VERSION_BUILDMETA_PREFIX = "buildmeta.prefix";
+ /**
+ * The major version property key.
+ */
+ public static final String KEY_VERSION_MAJOR = "major";
+ /**
+ * The minor version property key.
+ */
+ public static final String KEY_VERSION_MINOR = "minor";
+ /**
+ * The patch version property key.
+ */
+ public static final String KEY_VERSION_PATCH = "patch";
+ /**
+ * The pre-release version property key.
+ */
+ public static final String KEY_VERSION_PRERELEASE = "prerelease";
+ /**
+ * The pre-release prefix property key.
+ */
+ public static final String KEY_VERSION_PRERELEASE_PREFIX = "prerelease.prefix";
+ /**
+ * The project property key.
+ */
+ public static final String KEY_VERSION_PROJECT = "project";
+ /**
+ * The version separator property key.
+ */
+ public static final String KEY_VERSION_SEPARATOR = "separator";
+ /**
+ * The kotlin type.
+ */
+ public static final String KOTLIN_TYPE = "kt";
+ /**
+ * The argument used to specify the project location.
+ */
+ public static final String SEMVER_PROJECT_DIR_ARG = "semver.project.dir";
- /**
- * The default major version.
- */
- public static final int DEFAULT_MAJOR = 1;
-
- /**
- * The default minor version.
- */
- public static final int DEFAULT_MINOR = 0;
-
- /**
- * The default patch version.
- */
- public static final int DEFAULT_PATCH = 0;
-
- /**
- * The default Velocity template.
- */
- public static final String DEFAULT_TEMPLATE = "version.vm";
-
- /**
- * The empty string.
- */
- public static final String EMPTY = "";
-
- /**
- * The build metadata property key.
- */
- public static final String KEY_VERSION_BUILDMETA = "version.buildmeta";
-
- /**
- * The major version property key.
- */
- public static final String KEY_VERSION_MAJOR = "version.major";
-
- /**
- * The minor version property key.
- */
- public static final String KEY_VERSION_MINOR = "version.minor";
-
- /**
- * The patch version property key.
- */
- public static final String KEY_VERSION_PATCH = "version.patch";
-
- /**
- * The pre-release version property key.
- */
- public static final String KEY_VERSION_PRERELEASE = "version.prerelease";
-
- /**
- * The project property key.
- */
- public static final String KEY_VERSION_PROJECT = "version.project";
-
- /**
- * The velocity properties name.
- */
- public static final String VELOCITY_PROPERTIES = "velocity.properties";
-
- /**
- * Disables the default constructor.
- *
- * @throws UnsupportedOperationException if an error occurred. if the constructor is called.
- */
- private Constants()
- throws UnsupportedOperationException
- {
- throw new UnsupportedOperationException("Illegal constructor call.");
- }
-}
\ No newline at end of file
+ /**
+ * Disables the default constructor.
+ */
+ private Constants() {
+ throw new UnsupportedOperationException("Illegal constructor call.");
+ }
+}
diff --git a/src/main/java/net/thauvin/erik/semver/Version.java b/src/main/java/net/thauvin/erik/semver/Version.java
index fd1c986..821677f 100644
--- a/src/main/java/net/thauvin/erik/semver/Version.java
+++ b/src/main/java/net/thauvin/erik/semver/Version.java
@@ -1,7 +1,7 @@
/*
* Version.java
*
- * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net)
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
package net.thauvin.erik.semver;
import java.lang.annotation.ElementType;
@@ -39,41 +40,179 @@ import java.lang.annotation.Target;
/**
* The Version
class implements the annotation interface.
*
- * @author Erik C. Thauvin
+ * @author Erik C. Thauvin
* @created 2016-01-13
* @since 1.0
*/
+@SuppressWarnings("SameReturnValue")
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
-public @interface Version
-{
- String buildmeta() default Constants.EMPTY;
+public @interface Version {
+ /**
+ * Returns the build metadata version.
+ *
+ * @return The build metadata version.
+ */
+ String buildMeta() default Constants.EMPTY;
- String buildmetaKey() default Constants.KEY_VERSION_BUILDMETA;
+ /**
+ * Returns the build metadata key.
+ *
+ * @return The build metadata key.
+ */
+ String buildMetaKey() default Constants.KEY_VERSION_BUILDMETA;
- String className() default Constants.DEFAULT_CLASS_NAME;
+ /**
+ * Returns the build metadata prefix.
+ *
+ * @return The build metadata prefix.
+ */
+ String buildMetaPrefix() default Constants.DEFAULT_BUILDMETA_PREFIX;
- int major() default Constants.DEFAULT_MAJOR;
+ /**
+ * Returns the build metadata prefix key.
+ *
+ * @return The build metadata prefix key.
+ */
+ String buildMetaPrefixKey() default Constants.KEY_VERSION_BUILDMETA_PREFIX;
- String majorKey() default Constants.KEY_VERSION_MAJOR;
+ /**
+ * Returns the class name.
+ *
+ * @return The class name.
+ */
+ String className() default Constants.DEFAULT_CLASS_NAME;
- int minor() default Constants.DEFAULT_MINOR;
+ /**
+ * Returns the keys prefix.
+ *
+ * @return The keys prefix.
+ */
+ String keysPrefix() default Constants.DEFAULT_KEYS_PREFIX;
- String minorKey() default Constants.KEY_VERSION_MINOR;
+ /**
+ * Returns the major version.
+ *
+ * @return The major version.
+ */
+ int major() default Constants.DEFAULT_MAJOR;
- int patch() default Constants.DEFAULT_PATCH;
+ /**
+ * Returns the major key.
+ *
+ * @return The major key.
+ */
+ String majorKey() default Constants.KEY_VERSION_MAJOR;
- String patchKey() default Constants.KEY_VERSION_PATCH;
+ /**
+ * Returns the minor version.
+ *
+ * @return The build minor version.
+ */
+ int minor() default Constants.DEFAULT_MINOR;
- String prerelease() default Constants.EMPTY;
+ /**
+ * Returns the minor key.
+ *
+ * @return The minor key.
+ */
+ String minorKey() default Constants.KEY_VERSION_MINOR;
- String prereleaseKey() default Constants.KEY_VERSION_PRERELEASE;
+ /**
+ * Returns the package name.
+ *
+ * @return The package name .
+ */
+ String packageName() default Constants.EMPTY;
- String project() default Constants.EMPTY;
+ /**
+ * Returns the patch version.
+ *
+ * @return The patch version.
+ */
+ int patch() default Constants.DEFAULT_PATCH;
- String projectKey() default Constants.KEY_VERSION_PROJECT;
+ /**
+ * Returns the patch key.
+ *
+ * @return The patch key.
+ */
+ String patchKey() default Constants.KEY_VERSION_PATCH;
- String properties() default Constants.EMPTY;
+ /**
+ * Returns the pre-release version.
+ *
+ * @return The pre-release version.
+ */
+ String preRelease() default Constants.EMPTY;
- String template() default Constants.DEFAULT_TEMPLATE;
-}
\ No newline at end of file
+ /**
+ * Returns the pre-release key.
+ *
+ * @return The pre-release key.
+ */
+ String preReleaseKey() default Constants.KEY_VERSION_PRERELEASE;
+
+ /**
+ * Returns the pre-release prefix.
+ *
+ * @return The pre-release prefix.
+ */
+ String preReleasePrefix() default Constants.DEFAULT_PRERELEASE_PREFIX;
+
+ /**
+ * Returns the pre-release prefix key.
+ *
+ * @return The pre-release prefix key.
+ */
+ String preReleasePrefixKey() default Constants.KEY_VERSION_PRERELEASE_PREFIX;
+
+ /**
+ * Returns the project name.
+ *
+ * @return The project name.
+ */
+ String project() default Constants.EMPTY;
+
+ /**
+ * Returns the project key.
+ *
+ * @return The project.
+ */
+ String projectKey() default Constants.KEY_VERSION_PROJECT;
+
+ /**
+ * Returns the properties file name.
+ *
+ * @return The properties file name.
+ */
+ String properties() default Constants.EMPTY;
+
+ /**
+ * Returns the version separator.
+ *
+ * @return The separator.
+ */
+ String separator() default Constants.DEFAULT_SEPARATOR;
+
+ /**
+ * Returns the version separator key.
+ *
+ * @return The separator key.
+ */
+ String separatorKey() default Constants.KEY_VERSION_SEPARATOR;
+
+ /**
+ * Returns the template name.
+ *
+ * @return The template.
+ */
+ String template() default Constants.DEFAULT_JAVA_TEMPLATE;
+
+ /**
+ * Returns the template type.
+ *
+ * @return The type.
+ */
+ String type() default Constants.DEFAULT_JAVA_TYPE;
+}
diff --git a/src/main/java/net/thauvin/erik/semver/VersionInfo.java b/src/main/java/net/thauvin/erik/semver/VersionInfo.java
index e77f71b..b2ea193 100644
--- a/src/main/java/net/thauvin/erik/semver/VersionInfo.java
+++ b/src/main/java/net/thauvin/erik/semver/VersionInfo.java
@@ -1,7 +1,7 @@
/*
* VersionInfo.java
*
- * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net)
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,208 +29,312 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
package net.thauvin.erik.semver;
/**
* The VersionInfo
class is used to hold and retrieve the semantic version values.
*
- * @author Erik C. Thauvin
+ * @author Erik C. Thauvin
* @created 2016-01-16
* @since 1.0
*/
-public class VersionInfo
-{
- private final long epoch = System.currentTimeMillis();
+@SuppressWarnings("PMD.DataClass")
+public class VersionInfo {
+ private final long epoch = System.currentTimeMillis();
- private String buildmeta;
+ private String buildMeta;
+ private String buildMetaPrefix;
+ private String className;
+ private int major;
+ private int minor;
+ private String packageName;
+ private int patch;
+ private String preRelease;
+ private String preReleasePrefix;
+ private String project;
+ private String separator;
- private int major;
- private int minor;
+ /**
+ * Creates a new object with default values.
+ */
+ public VersionInfo() {
+ buildMeta = Constants.EMPTY;
+ buildMetaPrefix = Constants.DEFAULT_BUILDMETA_PREFIX;
+ className = Constants.DEFAULT_CLASS_NAME;
+ minor = Constants.DEFAULT_MINOR;
+ packageName = Constants.EMPTY;
+ patch = Constants.DEFAULT_PATCH;
+ preRelease = Constants.EMPTY;
+ preReleasePrefix = Constants.DEFAULT_PRERELEASE_PREFIX;
+ project = Constants.EMPTY;
+ separator = Constants.DEFAULT_SEPARATOR;
+ major = Constants.DEFAULT_MAJOR;
+ }
- private int patch;
+ /**
+ * Creates a new object with values from a {@link net.thauvin.erik.semver.VersionInfo VersionInfo} object.
+ *
+ * @param version The version object.
+ */
+ public VersionInfo(final Version version) {
+ buildMeta = version.buildMeta();
+ buildMetaPrefix = version.buildMetaPrefix();
+ className = version.className();
+ major = version.major();
+ minor = version.minor();
+ packageName = version.packageName();
+ patch = version.patch();
+ preRelease = version.preRelease();
+ preReleasePrefix = version.preReleasePrefix();
+ project = version.project();
+ separator = version.separator();
+ }
- private String prerelease;
+ /**
+ * Returns the build meta-data.
+ *
+ * @return The build meta-data.
+ */
+ public String getBuildMeta() {
+ return buildMeta;
+ }
- private String project;
+ /**
+ * Returns the meta-data prefix.
+ *
+ * @return The meta-data prefix.
+ */
+ public String getBuildMetaPrefix() {
+ return buildMetaPrefix;
+ }
- /**
- * Creates a new object with default values
- */
- public VersionInfo()
- {
- major = Constants.DEFAULT_MAJOR;
- minor = Constants.DEFAULT_MINOR;
- patch = Constants.DEFAULT_PATCH;
- buildmeta = Constants.EMPTY;
- prerelease = Constants.EMPTY;
- project = Constants.EMPTY;
- }
+ /**
+ * Returns the class name.
+ *
+ * @return The class name.
+ */
+ public String getClassName() {
+ return className;
+ }
- /**
- * Creates a new object with values from a {@link net.thauvin.erik.semver.Version Version} object.
- *
- * @param version The version object.
- */
- public VersionInfo(final Version version)
- {
- major = version.major();
- minor = version.minor();
- patch = version.patch();
- buildmeta = version.buildmeta();
- prerelease = version.prerelease();
- project = version.project();
- }
+ /**
+ * Returns the build epoch/Unix timestamp.
+ *
+ * @return The build epoch.
+ */
+ public long getEpoch() {
+ return epoch;
+ }
- /**
- * Returns the build metadata.
- *
- * @return The build metadata.
- */
- public String getBuildMetadata()
- {
- return buildmeta;
- }
+ /**
+ * Returns the major version.
+ *
+ * @return The major version.
+ */
+ public int getMajor() {
+ return major;
+ }
- /**
- * Sets the build metadata.
- *
- * @param buildmeta The new build metadata.
- */
- public void setBuildMetadata(final String buildmeta)
- {
- this.buildmeta = buildmeta;
- }
+ /**
+ * Returns the major version.
+ *
+ * @return The major version.
+ */
+ public int getMinor() {
+ return minor;
+ }
- /**
- * Returns the build epoch/Unix timestamp.
- *
- * @return The build epoch.
- */
- public long getEpoch()
- {
- return epoch;
- }
+ /**
+ * Returns the package name.
+ *
+ * @return The package name.
+ */
+ public String getPackageName() {
+ return packageName;
+ }
- /**
- * Returns the major version.
- *
- * @return The major version.
- */
- public int getMajor()
- {
- return major;
- }
+ /**
+ * Returns the patch version.
+ *
+ * @return The patch version.
+ */
+ public int getPatch() {
+ return patch;
+ }
- /**
- * Sets the major version.
- *
- * @param major The new major version.
- */
- public void setMajor(final int major)
- {
- this.major = major;
- }
+ /**
+ * Returns the pre-release version.
+ *
+ * @return The pre-release version.
+ */
+ public String getPreRelease() {
+ return preRelease;
+ }
- /**
- * Returns the major version.
- *
- * @return The major version.
- */
- public int getMinor()
- {
- return minor;
- }
+ /**
+ * Returns the pre-release prefix.
+ *
+ * @return The pre-release prefix.
+ */
+ public String getPreReleasePrefix() {
+ return preReleasePrefix;
+ }
- /**
- * Sets the minor version.
- *
- * @param minor The new minor version.
- */
- public void setMinor(final int minor)
- {
- this.minor = minor;
- }
+ /**
+ * Returns the project name.
+ *
+ * @return The project name.
+ */
+ public String getProject() {
+ return project;
+ }
- /**
- * Returns the patch version.
- *
- * @return The patch version.
- */
- public int getPatch()
- {
- return patch;
- }
+ /**
+ * Sames as {@link #getVersion()}.
+ *
+ * @return The version string.
+ */
+ public String getSemver() {
+ return getVersion();
+ }
- /**
- * Sets the patch version.
- *
- * @param patch The new patch version.
- */
- public void setPatch(final int patch)
- {
- this.patch = patch;
- }
+ /**
+ * Returns the version separator.
+ *
+ * @return The version separator.
+ */
+ public String getSeparator() {
+ return separator;
+ }
- /**
- * Returns the pre-release version.
- *
- * @return The pre-release version.
- */
- public String getPreRelease()
- {
- return prerelease;
- }
+ /**
+ * Returns the full version string.
+ *
+ *
+ *
+ *
+ *
+ * [MAJOR][SEPARATOR][MINOR][SEPARATOR][PATCH][[PRERELEASE-PREFIX][PRERELEASE]][[BUILDMETA-PREFIX][BUILDMETA]]
+ *
+ *
+ *
+ *
+ * @return The version string.
+ */
+ public String getVersion() {
+ return major
+ + separator
+ + minor
+ + separator
+ + patch
+ + (!preRelease.isEmpty() ? preReleasePrefix + preRelease : "")
+ + (!buildMeta.isEmpty() ? buildMetaPrefix + buildMeta : "");
+ }
- /**
- * Sets the pre-release version.
- *
- * @param prerelease The new pre-release version.
- */
- public void setPreRelease(final String prerelease)
- {
- this.prerelease = prerelease;
- }
+ /**
+ * Sets the build meta-data.
+ *
+ * @param buildMeta The new build meta-data.
+ */
+ public void setBuildMeta(final String buildMeta) {
+ this.buildMeta = buildMeta;
+ }
- /**
- * Returns the project name.
- *
- * @return The project name.
- */
- public String getProject()
- {
- return project;
- }
+ /**
+ * Sets the meta-data prefix.
+ *
+ * @param buildMetaPrefix The meta-data prefix.
+ */
+ public void setBuildMetaPrefix(final String buildMetaPrefix) {
+ this.buildMetaPrefix = buildMetaPrefix;
+ }
- /**
- * Sets the project name.
- *
- * @param project The new project name.
- */
- public void setProject(String project)
- {
- this.project = project;
- }
+ /**
+ * Sets the class name.
+ *
+ * @param className The new class name.
+ */
+ public void setClassName(final String className) {
+ this.className = className;
+ }
- /**
- * Returns the full version string.
- * 1.0.0
1.0.0-beta
1.0.0+20160124144700
1.0.0-alpha+001
- * MAJOR.MINOR.PATCH[-PRERELEASE][+BUILDMETADATA]
- *
- *
- * @return The version string.
- */
- public String getVersion()
- {
- return "" + major + '.' + minor + '.' + patch + (prerelease.length() > 0 ? '-' + prerelease : "") + (
- buildmeta.length() > 0 ? '+' + buildmeta : "");
- }
-}
\ No newline at end of file
+ /**
+ * Sets the major version.
+ *
+ * @param major The new major version.
+ */
+ public void setMajor(final int major) {
+ this.major = major;
+ }
+
+ /**
+ * Sets the minor version.
+ *
+ * @param minor The new minor version.
+ */
+ public void setMinor(final int minor) {
+ this.minor = minor;
+ }
+
+ /**
+ * Sets the package name.
+ *
+ * @param packageName The new package name.
+ */
+ public void setPackageName(final String packageName) {
+ this.packageName = packageName;
+ }
+
+ /**
+ * Sets the patch version.
+ *
+ * @param patch The new patch version.
+ */
+ public void setPatch(final int patch) {
+ this.patch = patch;
+ }
+
+ /**
+ * Sets the pre-release version.
+ *
+ * @param preRelease The new pre-release version.
+ */
+ public void setPreRelease(final String preRelease) {
+ this.preRelease = preRelease;
+ }
+
+ /**
+ * Sets the pre-release prefix.
+ *
+ * @param preReleasePrefix The new pre-release prefix.
+ */
+ public void setPreReleasePrefix(final String preReleasePrefix) {
+ this.preReleasePrefix = preReleasePrefix;
+ }
+
+ /**
+ * Sets the project name.
+ *
+ * @param project The new project name.
+ */
+ public void setProject(final String project) {
+ this.project = project;
+ }
+
+ /**
+ * Sets the version separator.
+ *
+ * @param separator The new version separator.
+ */
+ public void setSeparator(final String separator) {
+ this.separator = separator;
+ }
+}
diff --git a/src/main/java/net/thauvin/erik/semver/VersionProcessor.java b/src/main/java/net/thauvin/erik/semver/VersionProcessor.java
index 3228ec1..3ffd457 100644
--- a/src/main/java/net/thauvin/erik/semver/VersionProcessor.java
+++ b/src/main/java/net/thauvin/erik/semver/VersionProcessor.java
@@ -1,7 +1,7 @@
/*
* VersionProcessor.java
*
- * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net)
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,11 +29,12 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
package net.thauvin.erik.semver;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheNotFoundException;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
@@ -42,9 +43,10 @@ import javax.lang.model.element.ElementKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
-import javax.tools.JavaFileObject;
+import javax.tools.FileObject;
import java.io.*;
-import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
@@ -52,201 +54,231 @@ import java.util.Set;
/**
* The 1.0.0
1.0.0-beta
1.0.0+20160124144700
1.0.0-alpha+001
VersionProcessor
class implements a semantic version annotation processor.
*
- * @author Erik C. Thauvin
+ * @author Erik C. Thauvin
* @created 2016-01-13
* @since 1.0
*/
-public class VersionProcessor extends AbstractProcessor
-{
- private Filer filer;
+@SuppressWarnings({"PMD.GuardLogStatement", "PMD.BeanMembersShouldSerialize"})
+@SupportedOptions({Constants.KAPT_KOTLIN_GENERATED_OPTION_NAME, Constants.SEMVER_PROJECT_DIR_ARG})
+public class VersionProcessor extends AbstractProcessor {
+ private Filer filer;
- private Messager messager;
+ private Messager messager;
- private void error(final String s)
- {
- log(Diagnostic.Kind.ERROR, s);
- }
+ private static String getTemplate(final boolean isLocalTemplate, final Version version) {
+ final String template;
+ if (isLocalTemplate && Constants.DEFAULT_JAVA_TEMPLATE.equals(version.template())) {
+ template = Constants.DEFAULT_TEMPLATE_NAME;
+ } else if (Constants.DEFAULT_JAVA_TEMPLATE.equals(version.template()) && Constants.KOTLIN_TYPE
+ .equals(version.type())) {
+ template = Constants.DEFAULT_KOTLIN_TEMPLATE;
+ } else {
+ template = version.template();
+ }
+ return template;
+ }
- private void error(final String s, final Throwable t)
- {
- messager.printMessage(Diagnostic.Kind.ERROR, (t != null ? t.toString() : s));
- }
+ private Mustache compileTemplate(final File dir, final String template) throws IOException {
+ if (Constants.DEFAULT_JAVA_TEMPLATE.equals(template) || Constants.DEFAULT_KOTLIN_TEMPLATE.equals(template)) {
+ try (var in = getClass().getResourceAsStream("/" + template)) {
+ if (in != null) {
+ try (var reader = new BufferedReader(new InputStreamReader(in))) {
+ return new DefaultMustacheFactory().compile(reader, template);
+ }
+ } else {
+ throw new IOException("Resource not found: " + template);
+ }
+ }
+ } else {
+ return new DefaultMustacheFactory(dir).compile(template);
+ }
+ }
- private VersionInfo findValues(final Version version)
- throws IOException
- {
- final VersionInfo versionInfo;
+ private void error(final String s) {
+ log(Diagnostic.Kind.ERROR, s);
+ }
- if (version.properties().length() > 0)
- {
- versionInfo = new VersionInfo();
+ @SuppressWarnings("PMD.UnusedPrivateMethod")
+ private void error(final String s, final Throwable t) {
+ log(Diagnostic.Kind.ERROR, t != null ? t.toString() : s);
+ }
- final File propsFile = new File(version.properties());
- if (propsFile.exists())
- {
- note("Found properties: " + propsFile);
- final Properties p = new Properties();
+ private VersionInfo findValues(final Version version) throws IOException {
+ final var versionInfo = new VersionInfo(version);
- try (FileReader reader = new FileReader(propsFile))
- {
- p.load(reader);
+ if (!version.properties().isEmpty()) {
+ final var propsFile = getLocalFile(version.properties());
+ if (propsFile.isFile() && propsFile.canRead()) {
+ note("Found properties: " + propsFile.getName() + " (" + propsFile.getAbsoluteFile().getParent() + ')');
- versionInfo.setProject(p.getProperty(version.projectKey(), Constants.EMPTY));
- versionInfo.setMajor(parseIntProperty(p, version.majorKey(), Constants.DEFAULT_MAJOR));
- versionInfo.setMinor(parseIntProperty(p, version.minorKey(), Constants.DEFAULT_MINOR));
- versionInfo.setPatch(parseIntProperty(p, version.patchKey(), Constants.DEFAULT_PATCH));
- versionInfo.setBuildMetadata(p.getProperty(version.buildmetaKey(), Constants.EMPTY));
- versionInfo.setPreRelease(p.getProperty(version.prereleaseKey(), Constants.EMPTY));
- }
- }
- else
- {
- error("Could not find: " + propsFile);
- throw new FileNotFoundException(propsFile + " (The system cannot find the file specified)");
- }
- }
- else
- {
- versionInfo = new VersionInfo(version);
- }
+ final var p = new Properties();
- return versionInfo;
- }
+ try (var reader = new InputStreamReader(
+ Files.newInputStream(propsFile.toPath()), StandardCharsets.UTF_8)) {
+ p.load(reader);
- /**
- * {@inheritDoc}
- */
- @Override
- public SetVersion
class containing the semantic version (major, minor, patch, etc.) that is read from a Properties file or defined in the annotation.
+
+
+ GeneratedVersion
class containing the semantic
+version (major, minor, patch, etc.) that is read from a Properties file or defined in the annotation.
@since 1.0
-
-
+
+
diff --git a/src/main/resources/semver-kt.mustache b/src/main/resources/semver-kt.mustache
new file mode 100644
index 0000000..cf53df5
--- /dev/null
+++ b/src/main/resources/semver-kt.mustache
@@ -0,0 +1,38 @@
+/*
+ * This file is automatically generated.
+ * Do not modify! -- ALL CHANGES WILL BE ERASED!
+ */
+
+package {{packageName}}
+
+import java.util.Date
+
+/**
+ * Provides semantic version information.
+ *
+ * @author Semantic Version Annotation Processor
+ */
+object {{className}} {
+ @JvmField
+ val PROJECT = "{{project}}"
+ @JvmField
+ val BUILDDATE = Date({{epoch}}L)
+ @JvmField
+ val MAJOR = {{major}}
+ @JvmField
+ val MINOR = {{minor}}
+ @JvmField
+ val PATCH = {{patch}}
+ @JvmField
+ val PRERELEASE = "{{preRelease}}"
+ @JvmField
+ val PRERELEASE_PREFIX = "{{preReleasePrefix}}"
+ @JvmField
+ val BUILDMETA = "{{buildMeta}}"
+ @JvmField
+ val BUILDMEATA_PREFIX = "{{buildMetaPrefix}}"
+ @JvmField
+ val SEPARATOR = "{{separator}}"
+ @JvmField
+ val VERSION = "{{version}}"
+}
diff --git a/src/main/resources/semver.mustache b/src/main/resources/semver.mustache
new file mode 100644
index 0000000..d9eb417
--- /dev/null
+++ b/src/main/resources/semver.mustache
@@ -0,0 +1,34 @@
+/*
+ * This file is automatically generated.
+ * Do not modify! -- ALL CHANGES WILL BE ERASED!
+ */
+
+package {{packageName}};
+
+import java.util.Date;
+
+/**
+ * Provides semantic version information.
+ *
+ * @author Semantic Version Annotation Processor
+ */
+public final class {{className}} {
+ public static final String PROJECT = "{{project}}";
+ public static final Date BUILDDATE = new Date({{epoch}}L);
+ public static final int MAJOR = {{major}};
+ public static final int MINOR = {{minor}};
+ public static final int PATCH = {{patch}};
+ public static final String PRERELEASE = "{{preRelease}}";
+ public static final String PRERELEASE_PREFIX = "{{preReleasePrefix}}";
+ public static final String BUILDMETA = "{{buildMeta}}";
+ public static final String BUILDMETA_PREFIX = "{{buildMetaPrefix}}";
+ public static final String SEPARATOR = "{{separator}}";
+ public static final String VERSION = "{{version}}";
+
+ /**
+ * Disables the default constructor.
+ */
+ private {{className}}() {
+ throw new UnsupportedOperationException("Illegal constructor call.");
+ }
+}
diff --git a/src/main/resources/velocity.properties b/src/main/resources/velocity.properties
deleted file mode 100644
index ba28119..0000000
--- a/src/main/resources/velocity.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-runtime.log.logsystem.class = org.apache.velocity.runtime.log.SystemLogChute
-resource.loader = file, class
-file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader
-class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
\ No newline at end of file
diff --git a/src/main/resources/version.vm b/src/main/resources/version.vm
deleted file mode 100644
index 5c4d863..0000000
--- a/src/main/resources/version.vm
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is automatically generated by the Semantic Version Annotation Processor.
- * Do not modify this file -- YOUR CHANGES WILL BE ERASED!
- */
-package ${packageName};
-
-import java.util.Date;
-
-/**
- * This class provides semantic version information.
- *
- * @author Semantic Version Annotation Processor
- */
-public final class ${className} {
- private final static String buildmeta = "${buildmeta}";
- private final static Date date = new Date(${epoch}L);
- private final static int major = ${major};
- private final static int minor = ${minor};
- private final static int patch = ${patch};
- private final static String prerelease = "${prerelease}";
- private final static String project = "${project}";
-
- /**
- * Returns the build date.
- *
- * @return The build date.
- */
- public static Date getBuildDate() {
- return date;
- }
-
- /**
- * Returns the full version.
- *
- * @return The full version string.
- */
- public static String getVersion() {
- return "" + getMajor() + '.' + getMinor() + '.' + getPatch() + getPreRelease() + getBuildMetadata();
- }
-
- /**
- * Returns the major version.
- *
- * @return The major version.
- */
- public static int getMajor() {
- return major;
- }
-
- /**
- * Returns the minor version.
- *
- * @return The minor version.
- */
- public static int getMinor() {
- return minor;
- }
-
- /**
- * Returns the patch version.
- *
- * @return The patch version.
- */
- public static int getPatch() {
- return patch;
- }
-
- /**
- * Returns the pre-release version.
- *
- * @return The pre-release version, if any.
- */
- public static String getPreRelease() {
- if (prerelease.length() > 0) {
- return '-' + prerelease;
- }
-
- return "";
- }
-
- /**
- * Returns the project name.
- *
- * @return The project name, if any.
- */
- public static String getProject() {
- return project;
- }
-
- /**
- * Returns the build metadata.
- *
- * @return The build metadata, if any.
- */
- public static String getBuildMetadata() {
- if (buildmeta.length() > 0) {
- return '+' + buildmeta;
- }
-
- return "";
- }
-}
\ No newline at end of file
diff --git a/example/src/main/java/net/thauvin/erik/semver/example/Example.java b/src/test/java/net/thauvin/erik/semver/ConstantsTest.java
similarity index 54%
rename from example/src/main/java/net/thauvin/erik/semver/example/Example.java
rename to src/test/java/net/thauvin/erik/semver/ConstantsTest.java
index 51210dc..c82f718 100644
--- a/example/src/main/java/net/thauvin/erik/semver/example/Example.java
+++ b/src/test/java/net/thauvin/erik/semver/ConstantsTest.java
@@ -1,7 +1,7 @@
/*
- * Example.java
+ * ConstantsTest.java
*
- * Copyright (c) 2016, Erik C. Thauvin (erik@thauvin.net)
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,27 +29,45 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-package net.thauvin.erik.semver.example;
-import net.thauvin.erik.semver.Version;
+package net.thauvin.erik.semver;
-import java.text.SimpleDateFormat;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * The Example
class.
+ * The ConstantsTest
class.
*
- * @author Erik C. Thauvin
- * @created 2016-01-13
+ * @author Erik C. Thauvin
+ * @created 2019-04-14
* @since 1.0
*/
-@Version(properties = "version.properties")
-public class Example
-{
- public static void main(final String... args)
- {
- final SimpleDateFormat sdf = new SimpleDateFormat("'Built on' EEE, d MMM yyyy 'at' HH:mm:ss z");
+class ConstantsTest {
+ @Test
+ void testDefaults() {
+ assertEquals(1, Constants.DEFAULT_MAJOR, "major");
+ assertEquals(0, Constants.DEFAULT_MINOR, "minor");
+ assertEquals(0, Constants.DEFAULT_PATCH, "patch");
+ assertEquals("-", Constants.DEFAULT_PRERELEASE_PREFIX, "preRelease");
+ assertEquals("+", Constants.DEFAULT_BUILDMETA_PREFIX, "buildMeta");
+ assertEquals(".", Constants.DEFAULT_SEPARATOR, "separator");
+ }
- System.out.println(GeneratedVersion.getProject() + ' ' + GeneratedVersion.getVersion());
- System.out.println(sdf.format(GeneratedVersion.getBuildDate()));
- }
-}
\ No newline at end of file
+ @Test
+ void testTemplates() {
+ final ListVersionInfoTest
class.
+ *
+ * @author Erik C. Thauvin
+ * @created 2016-02-03
+ * @since 1.0
+ */
+class VersionInfoTest {
+ private VersionInfo versionInfo = new VersionInfo();
+
+ @SuppressWarnings("PMD.AvoidUsingHardCodedIP")
+ @Test
+ void testGetVersion() {
+ assertEquals("1.0.0", versionInfo.getVersion(), "getVersion(1.0.0)");
+
+ versionInfo.setMajor(3);
+
+ assertEquals("3.0.0", versionInfo.getVersion(), "getVersion(3.0.0)");
+
+ versionInfo.setMinor(2);
+
+ assertEquals("3.2.0", versionInfo.getVersion(), "getVersion(3.2.0)");
+
+ versionInfo.setPatch(1);
+
+ assertEquals("3.2.1", versionInfo.getVersion(), "getVersion(3.2.1)");
+
+ versionInfo.setPreRelease("beta");
+
+ assertEquals("3.2.1-beta", versionInfo.getVersion(), "getVersion(3.2.1-beta)");
+
+ versionInfo.setBuildMeta("001");
+
+ assertEquals("3.2.1-beta+001", versionInfo.getVersion(), "getVersion(3.2.1-beta+001)");
+
+ versionInfo.setPreReleasePrefix("+");
+
+ assertEquals("3.2.1+beta+001", versionInfo.getVersion(), "getVersion(3.2.1+beta+001)");
+
+ versionInfo.setPreReleasePrefix("-");
+
+ versionInfo.setPreRelease("");
+
+ assertEquals("3.2.1+001", versionInfo.getVersion(), "getVersion(3.2.1+001)");
+
+ versionInfo.setBuildMetaPrefix(".");
+
+ assertEquals("3.2.1.001", versionInfo.getVersion(), "getVersion(3.2.1.001)");
+
+ versionInfo.setBuildMetaPrefix("+");
+
+ versionInfo.setSeparator("-");
+
+ assertEquals("3-2-1+001", versionInfo.getVersion(), "getVersion(3-2-1+001)");
+
+ assertEquals(versionInfo.getSemver(), versionInfo.getVersion(),
+ "getVersion(3-2-1+001) = getSemver(3-2-1+001) ");
+ }
+
+ @Test
+ void testSetGet() {
+ versionInfo.setSeparator(".");
+
+ versionInfo.setMajor(1);
+
+ assertEquals(1, versionInfo.getMajor(), "getMajor(1)");
+
+ versionInfo.setMinor(2);
+
+ assertEquals(2, versionInfo.getMinor(), "getMinor(2)");
+
+ versionInfo.setPatch(3);
+
+ assertEquals(3, versionInfo.getPatch(), "getPatch(3)");
+
+ versionInfo.setPreRelease("alpha");
+
+ assertEquals("alpha", versionInfo.getPreRelease(), "getPreRelease(alpha)");
+
+ versionInfo.setBuildMeta("001");
+
+ assertEquals("001", versionInfo.getBuildMeta(), "getBuildMeta(001)");
+
+ versionInfo.setPackageName("com.example");
+
+ assertEquals("com.example", versionInfo.getPackageName(), "getPackageName(com.example)");
+
+ assertEquals("1.2.3-alpha+001", versionInfo.getVersion(), "getVersion(1.2.3-alpha+001)");
+
+ assertEquals(versionInfo.getSemver(), versionInfo.getVersion(), "getVersion() = getSemver()");
+
+ versionInfo.setBuildMetaPrefix("");
+
+ assertEquals("", versionInfo.getBuildMetaPrefix(), "getBuildMetaPrefix( )");
+
+ assertEquals("1.2.3-alpha001", versionInfo.getVersion(), "getVersion(1.2.3+alpha001)");
+
+ versionInfo.setPreReleasePrefix(".");
+
+ assertEquals(".", versionInfo.getPreReleasePrefix(), "getPreReleasePrefix(.)");
+
+ assertEquals("1.2.3.alpha001", versionInfo.getVersion(), "getVersion(1.2.3.alpha001");
+
+ versionInfo.setSeparator("-");
+
+ assertEquals("-", versionInfo.getSeparator(), "getSeparator(-)");
+
+ assertEquals("1-2-3.alpha001", versionInfo.getVersion(), "getVersion(1-2-3.alpha001)");
+
+ versionInfo.setProject("My Example");
+
+ assertEquals("My Example", versionInfo.getProject(), "getProject(My Example)");
+
+ versionInfo.setClassName("Example");
+
+ assertEquals("Example", versionInfo.getClassName(), "getClassName(Example");
+
+ assertTrue((versionInfo.getEpoch() - new Date().getTime()) < 1000, "buildDate - now < 1s");
+ }
+
+ @Test
+ void testVersionInfo() {
+ final Version version = new VersionTest();
+ versionInfo = new VersionInfo(version);
+
+ assertEquals(version.major(), versionInfo.getMajor(), "getMajor(major)");
+
+ assertEquals(version.minor(), versionInfo.getMinor(), "getMinor(minor)");
+
+ assertEquals(version.patch(), versionInfo.getPatch(), "getPatch(patch)");
+
+ assertEquals(version.preRelease(), versionInfo.getPreRelease(), "getPreRelease(preRelease)");
+
+ assertEquals(version.preReleasePrefix(), versionInfo.getPreReleasePrefix(),
+ "getPreReleasePrefix(preReleasePrefix)");
+
+ assertEquals(version.buildMeta(), versionInfo.getBuildMeta(), "getBuildMeta(buildMeta)");
+
+ assertEquals(version.buildMetaPrefix(), versionInfo.getBuildMetaPrefix(),
+ "getBuildMetaPrefix(buildMetaPrefix)");
+
+ assertEquals(version.packageName(), versionInfo.getPackageName(), "getPackageName(packageName)");
+
+ assertEquals(versionInfo.getVersion(),
+ version.major() + "." + version.minor() + '.' + version.patch() + '-' + version.preRelease() + '+'
+ + version.buildMeta(), "getVersion(version)");
+
+ assertEquals(versionInfo.getSemver(), versionInfo.getVersion(), "getVersion(version) = getSemver(version)");
+
+ assertEquals(version.project(), versionInfo.getProject(), "getProject(project)");
+
+ assertEquals(version.className(), versionInfo.getClassName(), "getClassName(className)");
+ }
+}
diff --git a/src/test/java/net/thauvin/erik/semver/VersionProcessorTest.java b/src/test/java/net/thauvin/erik/semver/VersionProcessorTest.java
new file mode 100644
index 0000000..c49af74
--- /dev/null
+++ b/src/test/java/net/thauvin/erik/semver/VersionProcessorTest.java
@@ -0,0 +1,186 @@
+/*
+ * VersionProcessorTest.java
+ *
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of this project nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.semver;
+
+import com.github.mustachejava.Mustache;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Properties;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The VersionProcessorTest
class.
+ *
+ * @author Erik C. Thauvin
+ * @created 2019-04-02
+ * @since 1.2.0
+ */
+class VersionProcessorTest {
+ private final VersionProcessor processor = new VersionProcessor();
+ private final VersionTest version = new VersionTest();
+
+ /**
+ * Compares two strings by removing all line separators and whitespace.
+ *
+ * @param text1 The first text to compare
+ * @param text2 The second text to compare
+ * @return true if the texts are equivalent when line separators are ignored, false otherwise
+ */
+ static boolean compareTextIgnoringLineSeparators(String text1, String text2) {
+ // Handle null cases
+ if (text1 == null && text2 == null) {
+ return true;
+ }
+ if (text1 == null || text2 == null) {
+ return false;
+ }
+
+ // Remove all line separators and whitespace
+ var cleanedText1 = text1.replaceAll("\\r?\\n|\\r|\\s", "");
+ var cleanedText2 = text2.replaceAll("\\r?\\n|\\r|\\s", "");
+
+ // Compare the cleaned strings
+ return cleanedText1.equals(cleanedText2);
+ }
+
+ @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
+ @Test
+ void testCompileTemplate()
+ throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
+ final var method = processor.getClass().getDeclaredMethod("compileTemplate", File.class, String.class);
+ method.setAccessible(true);
+
+ final var mustache = (Mustache) method.invoke(processor, new File("src/main/resources"),
+ Constants.DEFAULT_JAVA_TEMPLATE);
+
+ assertEquals(Constants.DEFAULT_JAVA_TEMPLATE, mustache.getName(), Constants.DEFAULT_JAVA_TEMPLATE);
+
+ try (var writer = new StringWriter()) {
+ mustache.execute(writer, version).flush();
+ assertTrue(compareTextIgnoringLineSeparators(
+ String.format("/*" +
+ " * This file is automatically generated." +
+ " * Do not modify! -- ALL CHANGES WILL BE ERASED!" +
+ " */" +
+ "package %s;" +
+ "import java.util.Date;" +
+ "/**" +
+ " * Provides semantic version information." +
+ " *" +
+ " * @author Semantic Version Annotation Processor" +
+ " */" +
+ "public final class %s {" +
+ " public static final String PROJECT = \"%s\";" +
+ " public static final Date BUILDDATE = new Date(L);" +
+ " public static final int MAJOR = %d;" +
+ " public static final int MINOR = %d;" +
+ " public static final int PATCH = %d;" +
+ " public static final String PRERELEASE = \"%s\";" +
+ " public static final String PRERELEASE_PREFIX = \"%s\";" +
+ " public static final String BUILDMETA = \"%s\";" +
+ " public static final String BUILDMETA_PREFIX = \"%s\";" +
+ " public static final String SEPARATOR = \"%s\";" +
+ " public static final String VERSION = \"\";" +
+ " /**" +
+ " * Disables the default constructor." +
+ " */" +
+ " private %s() {" +
+ " throw new UnsupportedOperationException(\"Illegal constructor call.\");" +
+ " }" +
+ "}", version.packageName(), version.className(), version.project(), version.major(),
+ version.minor(), version.patch(), version.preRelease(), version.preReleasePrefix(),
+ version.buildMeta(), version.buildMetaPrefix(), version.separator(), version.className()),
+ writer.toString()));
+ }
+ }
+
+ @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
+ @Test
+ void testFindValues() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ final var method = processor.getClass().getDeclaredMethod("findValues", Version.class);
+ method.setAccessible(true);
+ final var versionInfo = (VersionInfo) method.invoke(processor, version);
+
+ assertEquals("0-0-7:vodka++martini", versionInfo.getVersion(), "getVersion(0-0-7:vodka++martin)");
+ assertEquals("James Bond", versionInfo.getProject(), "getProject(James Bond)");
+ }
+
+ @Test
+ void testGetSupportedAnnotationTypes() {
+ assertTrue(processor.getSupportedAnnotationTypes().contains("net.thauvin.erik.semver.Version"));
+ }
+
+ @Test
+ void testGetSupportedSourceVersion() {
+ assertTrue(processor.getSupportedSourceVersion().ordinal() >= 17);
+ }
+
+ @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
+ @Test
+ void testGetTemplate() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ final var method = processor.getClass().getDeclaredMethod("getTemplate", boolean.class, Version.class);
+ method.setAccessible(true);
+
+ assertEquals(version.template(), method.invoke(processor, true, version), version.template);
+ version.setTemplate(Constants.DEFAULT_JAVA_TEMPLATE);
+ assertEquals(Constants.DEFAULT_TEMPLATE_NAME, method.invoke(processor, true, version),
+ "default");
+ assertEquals(Constants.DEFAULT_KOTLIN_TEMPLATE, method.invoke(processor, false, version),
+ "kotlin");
+ }
+
+ @SuppressWarnings("PMD.AvoidAccessibilityAlteration")
+ @Test
+ void testParseIntProperty() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ final var p = new Properties();
+ p.setProperty("1", "1");
+ p.setProperty("2", "2.1");
+ p.setProperty("3", "zero");
+ p.setProperty("4", " 4 ");
+
+ final var method = processor.getClass().getDeclaredMethod("parseIntProperty", Properties.class, String.class,
+ int.class);
+ method.setAccessible(true);
+
+ assertEquals(1, method.invoke(processor, p, "1", -1), "parseIntProperty(1)");
+ assertEquals(-1, method.invoke(processor, p, "2", -1), "parseIntProperty(2.1)");
+ assertEquals(-1, method.invoke(processor, p, "3", -1), "parseIntProperty(zero)");
+ assertEquals(4, method.invoke(processor, p, "4", -1), "parseIntProperty( 4 )");
+ }
+}
diff --git a/src/test/java/net/thauvin/erik/semver/VersionTest.java b/src/test/java/net/thauvin/erik/semver/VersionTest.java
new file mode 100644
index 0000000..e27f316
--- /dev/null
+++ b/src/test/java/net/thauvin/erik/semver/VersionTest.java
@@ -0,0 +1,176 @@
+/*
+ * VersionTest.java
+ *
+ * Copyright (c) 2016-2024, Erik C. Thauvin (erik@thauvin.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of this project nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.thauvin.erik.semver;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The VersionTest
class.
+ *
+ * @author Erik C. Thauvin
+ * @created 2019-04-02
+ * @since 1.2.0
+ */
+@SuppressWarnings({"ClassExplicitlyAnnotation", "PMD.TestClassWithoutTestCases"})
+class VersionTest implements Version {
+ String template = "myversion.mustache";
+
+ @Override
+ public Class extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String buildMeta() {
+ return "007";
+ }
+
+ @Override
+ public String buildMetaKey() {
+ return "meta";
+ }
+
+ @Override
+ public String buildMetaPrefix() {
+ return "+";
+ }
+
+ @Override
+ public String buildMetaPrefixKey() {
+ return "meta.prefix";
+ }
+
+ @Override
+ public String className() {
+ return "MyTest";
+ }
+
+ @Override
+ public String keysPrefix() {
+ return "build.";
+ }
+
+ @Override
+ public int major() {
+ return 2;
+ }
+
+ @Override
+ public String majorKey() {
+ return "major";
+ }
+
+ @Override
+ public int minor() {
+ return 17;
+ }
+
+ @Override
+ public String minorKey() {
+ return "minor";
+ }
+
+ @Override
+ public String packageName() {
+ return "com.foo.example";
+ }
+
+ @Override
+ public int patch() {
+ return 52;
+ }
+
+ @Override
+ public String patchKey() {
+ return "patch";
+ }
+
+ @Override
+ public String preRelease() {
+ return "beta";
+ }
+
+ @Override
+ public String preReleaseKey() {
+ return "prerelease";
+ }
+
+ @Override
+ public String preReleasePrefix() {
+ return "-";
+ }
+
+ @Override
+ public String preReleasePrefixKey() {
+ return "prerelease.prefix";
+ }
+
+ @Override
+ public String project() {
+ return "My Test Project";
+ }
+
+ @Override
+ public String projectKey() {
+ return "project";
+ }
+
+ @Override
+ public String properties() {
+ return "test.properties";
+ }
+
+ @Override
+ public String separator() {
+ return ".";
+ }
+
+ @Override
+ public String separatorKey() {
+ return "separator";
+ }
+
+ @Override
+ public String template() {
+ return template;
+ }
+
+ @Override
+ public String type() {
+ return "kt";
+ }
+
+ public void setTemplate(final String template) {
+ this.template = template;
+ }
+}
diff --git a/test.properties b/test.properties
new file mode 100644
index 0000000..98cab4c
--- /dev/null
+++ b/test.properties
@@ -0,0 +1,9 @@
+build.major=0
+build.minor=0
+build.patch=7
+build.prerelease=vodka
+build.prerelease.prefix=:
+build.meta=martini
+build.meta.prefix=++
+build.separator=-
+build.project=James Bond
diff --git a/version.properties b/version.properties
deleted file mode 100644
index b69bd95..0000000
--- a/version.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Sun, 24 Jan 2016 23:55:10 -0800
-version.major=0
-version.minor=9
-version.patch=1
-version.buildmeta=
-version.prerelease=beta