├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── greetings.yml
│ ├── maven-central-push.yml
│ ├── maven-pr.yml
│ ├── pr-review.yml
│ └── update-wiki.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── checkstyle.xml
├── pom.xml
├── src
├── main
│ ├── java
│ │ └── com
│ │ │ └── sngular
│ │ │ └── annotation
│ │ │ ├── pact
│ │ │ ├── DslExclude.java
│ │ │ ├── Example.java
│ │ │ └── PactDslBodyBuilder.java
│ │ │ └── processor
│ │ │ ├── PactDslProcessor.java
│ │ │ ├── exception
│ │ │ ├── PactProcessorException.java
│ │ │ ├── TemplateFactoryException.java
│ │ │ └── TemplateGenerationException.java
│ │ │ ├── mapping
│ │ │ ├── BigDecimalMapping.java
│ │ │ ├── BigIntegerMapping.java
│ │ │ ├── BooleanMapping.java
│ │ │ ├── ByteMapping.java
│ │ │ ├── CharMapping.java
│ │ │ ├── CustomDslModifier.java
│ │ │ ├── DateMapping.java
│ │ │ ├── DoubleMapping.java
│ │ │ ├── FloatMapping.java
│ │ │ ├── IntegerMapping.java
│ │ │ ├── LongMapping.java
│ │ │ ├── ShortMapping.java
│ │ │ ├── StringMapping.java
│ │ │ ├── TypeMapping.java
│ │ │ └── ZonedDateTimeMapping.java
│ │ │ ├── model
│ │ │ ├── ClassBuilderTemplate.java
│ │ │ ├── DslComplexField.java
│ │ │ ├── DslComplexTypeEnum.java
│ │ │ ├── DslField.java
│ │ │ ├── DslSimpleField.java
│ │ │ └── FieldValidations.java
│ │ │ └── template
│ │ │ ├── ClasspathTemplateLoader.java
│ │ │ └── TemplateFactory.java
│ └── resources
│ │ └── templates
│ │ └── templateDslBuilder.ftlh
└── test
│ ├── java
│ └── com
│ │ └── sngular
│ │ └── annotation
│ │ └── processor
│ │ ├── BasicDataTypeTest.java
│ │ ├── DateFormatTest.java
│ │ └── RandomValueGenerationTest.java
│ └── resources
│ ├── basic
│ ├── CharacterDataTypes.java
│ ├── CharacterDataTypesBuilder.java
│ ├── NumericDataTypes.java
│ └── NumericDataTypesBuilder.java
│ ├── complex
│ └── NestedObjects.java
│ ├── date
│ ├── DateDataTypes.java
│ └── DateDataTypesBuilder.java
│ └── random
│ ├── NumericDataTypes.java
│ └── NumericDataTypesBuilder.java
└── styles
└── OS3_Style_idea.xml
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Add the necessary files to be able to reproduce the issue.
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Screenshots**
20 | If applicable, add screenshots to help explain your problem.
21 |
22 |
23 | **Additional context**
24 | Add any other context about the problem here.
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/greetings.yml:
--------------------------------------------------------------------------------
1 | name: Greetings
2 |
3 | on: [pull_request, issues]
4 |
5 | jobs:
6 | greeting:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/first-interaction@v1
10 | continue-on-error: true
11 | with:
12 | repo-token: ${{ secrets.GITHUB_TOKEN }}
13 | issue-message: "Thank you for collaborating with the project by giving us feedback! Cheers!"
14 | pr-message: "Thank you for collaborating with the project to help us improve!"
15 |
--------------------------------------------------------------------------------
/.github/workflows/maven-central-push.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven (Push)
2 |
3 | on:
4 | push:
5 | branches: [main]
6 |
7 | jobs:
8 | check-pr-labels:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | pull-requests: read
12 | outputs:
13 | labels: ${{ steps.get-pr.outputs.pr_labels }}
14 | steps:
15 | - name: Get Pull Request information
16 | uses: 8BitJonny/gh-get-current-pr@2.2.0
17 | id: get-pr
18 |
19 | check-version:
20 | runs-on: ubuntu-latest
21 | needs: [check-pr-labels]
22 | if: ${{ contains(needs.check-pr-labels.outputs.labels, 'release') }}
23 | steps:
24 | - uses: actions/checkout@v3
25 | - name: Check if version is updated
26 | uses: avides/actions-project-version-check@v1.3
27 | id: engine_version_check
28 | with:
29 | token: ${{ secrets.GITHUB_TOKEN }}
30 | file-to-check: pom.xml
31 | continue-on-error: true
32 |
33 | build:
34 | runs-on: ubuntu-latest
35 | needs: [check-version, check-pr-labels]
36 | if: contains(needs.check-version.result, 'success')
37 | steps:
38 | - uses: actions/checkout@v2
39 | with:
40 | ref: ${{ github.head_ref }}
41 |
42 | - name: Set up JDK 17
43 | uses: actions/setup-java@v2
44 | with:
45 | java-version: "17"
46 | distribution: "adopt"
47 | server-id: ossrh
48 | server-username: MAVEN_USERNAME
49 | server-password: MAVEN_CENTRAL_TOKEN
50 | gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }}
51 | gpg-passphrase: MAVEN_GPG_PASSPHRASE
52 | - name: Cache Maven packages
53 | uses: actions/cache@v2
54 | with:
55 | path: ~/.m2
56 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
57 | restore-keys: ${{ runner.os }}-m2
58 |
59 | - name: Publish Maven Plugin to Maven Central Packages
60 | # Uses production profile to sign with gpg plugin
61 | run: |
62 | mvn -B install
63 | mvn -B deploy -P production
64 | env:
65 | MAVEN_USERNAME: ${{ secrets.JIRAID }}
66 | MAVEN_CENTRAL_TOKEN: ${{ secrets.JIRAPASS }}
67 | MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
68 | SIGN_KEY: ${{ secrets.JIRAID }}
69 | SIGN_KEY_ID: ${{ secrets.JIRAPASS }}
70 | SIGN_KEY_PASS: ${{ secrets.GPG_PASSPHRASE }}
71 |
72 | - name: Maven version
73 | id: get-version
74 | run: |
75 | echo "version=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)" | tee $GITHUB_OUTPUT
76 |
77 | - name: Create a Release
78 | uses: marvinpinto/action-automatic-releases@latest
79 | with:
80 | repo_token: ${{ secrets.GITHUB_TOKEN }}
81 | automatic_release_tag: ${{ steps.get-version.outputs.version }}
82 | prerelease: false
83 | title: "Maven Release ${{ steps.get-version.outputs.version }}"
84 |
--------------------------------------------------------------------------------
/.github/workflows/maven-pr.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven (PR)
2 |
3 | on:
4 | pull_request:
5 | types: [opened, synchronize, ready_for_review, labeled]
6 |
7 | concurrency: pr-${{ github.event.pull_request.id }}
8 |
9 | jobs:
10 | check-version:
11 | runs-on: ubuntu-latest
12 | if: ${{ contains(github.event.pull_request.labels.*.name, 'release') || contains(github.event.pull_request.labels.*.name, 'maven') }}
13 | steps:
14 | - uses: actions/checkout@v3
15 | continue-on-error: true
16 | - name: Check if version is updated
17 | uses: avides/actions-project-version-check@v1.3
18 | id: maven_processor_version_check
19 | with:
20 | token: ${{ secrets.GITHUB_TOKEN }}
21 | file-to-check: pom.xml
22 | continue-on-error: true
23 | - name: Warn about version specification
24 | if: ${{steps.maven_processor_version_check.outcome != 'success' }}
25 | uses: thollander/actions-comment-pull-request@v1
26 | with:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | message: Project version has not been updated in pom.xml. Please, update your version using https://semver.org specifications
29 | - name: Fail
30 | if: ${{steps.maven_processor_version_check.outcome != 'success' }}
31 | uses: cutenode/action-always-fail@v1
32 | - name: New software version
33 | if: ${{ steps.maven_processor_version_check.outcome == 'success' }}
34 | run: echo "New Pact Annotation Builder engine version is " ${{ steps.maven_processor_version_check.version }}
35 |
36 | build:
37 | runs-on: ubuntu-latest
38 | steps:
39 | - uses: actions/checkout@v3
40 | - name: Set up JDK 17
41 | uses: actions/setup-java@v2
42 | with:
43 | java-version: "17"
44 | distribution: "adopt"
45 | - name: Cache Maven packages
46 | uses: actions/cache@v2
47 | with:
48 | path: ~/.m2
49 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
50 | restore-keys: ${{ runner.os }}-m2
51 | - name: Build Maven Plugin
52 | # Uses production profile to sign with gpg plugin
53 | run: |
54 | mvn -B install
55 |
56 | check-labels:
57 | runs-on: ubuntu-latest
58 | if: github.event.pull_request.mergeable == true
59 | steps:
60 | - name: Warn about missing labels
61 | if: ${{ !contains(github.event.pull_request.labels.*.name, 'release') && !contains(github.event.pull_request.labels.*.name, 'documentation') && !contains(github.event.pull_request.labels.*.name, 'maven') && !contains(github.event.pull_request.labels.*.name, 'gradle')}}}
62 | uses: thollander/actions-comment-pull-request@v2
63 | with:
64 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65 | message: "This pull request hasn't been labeled as `release`, `gradle`, `maven` nor `documentation`. Please ensure this is intentional before merging."
66 | comment_tag: label-warn
67 |
--------------------------------------------------------------------------------
/.github/workflows/pr-review.yml:
--------------------------------------------------------------------------------
1 | name: Pull Request Approved
2 |
3 | on:
4 | pull_request_review:
5 | types: [submitted]
6 |
7 | concurrency: pr-${{ github.event.pull_request.id }}
8 |
9 | jobs:
10 | check-labels:
11 | runs-on: ubuntu-latest
12 | if: github.event.review.state == 'approved'
13 | steps:
14 | - name: Warn about missing labels
15 | if: ${{ !contains(github.event.pull_request.labels.*.name, 'release') && !contains(github.event.pull_request.labels.*.name, 'documentation')}}}
16 | uses: thollander/actions-comment-pull-request@v2
17 | with:
18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 | message: "This pull request hasn't been labeled as `release` nor `documentation`. Please ensure this is intentional before merging."
20 | comment_tag: label-warn
21 |
--------------------------------------------------------------------------------
/.github/workflows/update-wiki.yml:
--------------------------------------------------------------------------------
1 | name: Sync Docs (Merge)
2 |
3 | on:
4 | push:
5 | branches: [main]
6 |
7 | jobs:
8 | check-pr-labels:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | pull-requests: read
12 | outputs:
13 | labels: ${{ steps.get-pr.outputs.pr_labels }}
14 | steps:
15 | - name: Get Pull Request information
16 | uses: 8BitJonny/gh-get-current-pr@2.2.0
17 | id: get-pr
18 |
19 | update-wiki:
20 | runs-on: ubuntu-latest
21 | needs: [check-pr-labels]
22 | if: contains(needs.check-pr-labels.outputs.labels, 'documentation')
23 | steps:
24 | - name: Setup variables
25 | run: |
26 | echo "REPO_DEST=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}').wiki" >> $GITHUB_ENV
27 | shell: bash
28 | - name: Checkout SCS Pact Annotation Builder Plugin Repository
29 | run: git clone https://github.com/sngular/pact-annotation-builder.git pact-annotation-builder
30 | - name: Checkout SCS Pact Annotation Builder Plugin Wiki Repository
31 | run: git clone https://github.com/sngular/pact-annotation-builder.wiki.git wiki
32 | - name: Copy docs and consolidate links
33 | run: |
34 | cp -rf pact-annotation-builder/docs/* wiki/
35 | cd wiki
36 | grep -lr "(.*\.md)" *|xargs -r sed -i 's/\.md//g'
37 | echo ">"
38 | git diff-index --quiet HEAD & git status -s
39 | echo "<"
40 | git status
41 | echo ">"
42 | git diff-index --quiet HEAD & git status -s
43 | echo "<"
44 | echo "TO_BE_CANCELLED=$(if [[ $(git diff-index --quiet HEAD & git status -s) ]]; then echo "false"; else echo "true"; fi)" >> $GITHUB_ENV
45 | echo "$TO_BE_CANCELLED"
46 | - name: Setup git user
47 | if: ${{ env.TO_BE_CANCELLED == 'false' }}
48 | run: |
49 | git config --global user.name ${{ github.actor }}
50 | - name: Sync Wiki
51 | if: ${{ env.TO_BE_CANCELLED == 'false' }}
52 | run: |
53 | cd wiki
54 | git status
55 | git add .
56 | git commit -m "pact-annotation-builder documentation | GitHub Actions $GITHUB_WORKFLOW $GITHUB_RUN_NUMBER"
57 | git remote add origin-wiki "https://${{secrets.GITBOT_TOKEN}}@github.com/sngular/pact-annotation-builder.wiki.git"
58 | git push origin-wiki main
59 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # IntelliJ Files
26 | .idea
27 | *.iml
28 |
29 | # Target Folder
30 | target/
31 |
32 | # Pom bak file
33 | pom.xml.bak
34 | **/.gradle/
35 | **/build/
36 |
37 | # Visual Code
38 | .DS_Store
39 |
40 | **/bin/
41 | .vscode/
42 | **/.java-version
43 |
44 | *.bak
45 | dependency-reduced-pom*
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | First of all, thanks for taking the time to contribute!
4 |
5 | This file includes best practices and guidelines for contributing to our
6 | project. We encourage you to follow them and help us create a better product!
7 |
8 | ## Best practices
9 |
10 | - We follow a [code of conduct](#code-of-conduct), review it and honor it in all
11 | your interactions with the project.
12 | - When contributing to this repository, first create an issue to explain the
13 | change you want to make.
14 | - The issues will be preferably written in English, although Spanish is
15 | also acceptable.
16 | - The issue title should briefly summarize the proposal.
17 | - The issue body should include a description of the proposal with all the
18 | details, conditions, dependencies affected, charts, screenshots, etc.,
19 | that can help to further understand and evaluate the proposal.
20 | - Create a new branch before making any change in the repository. This branch
21 | should follow this format: #issue_ID_and_summary (for example,
22 | #23_add_new_provider).
23 | - When writing the code, follow our [style sheet](https://github.com/corunet/scs-multiapi-plugin/tree/main/styles/OSS_style_idea.xml).
24 | - Create commit messages that briefly describe the change applied, preferably in
25 | English.
26 |
27 | ## Pull request process
28 |
29 | 1. Ensure any install or build dependencies are solved before doing a build.
30 | 2. Update the README.md file with details of the changes. This includes new
31 | environment variables, exposed ports, useful file locations and container
32 | parameters.
33 | 3. Increase the version number in any examples files and in README.md to the new
34 | version that this pull request would represent. The versioning scheme we
35 | follow is [SemVer](http://semver.org/).
36 | 4. If your Pull Request corresponds to a new release, label it as `release` to
37 | create a new version of both the maven and gradle plugins. To create a new
38 | release for either of them individually you can use the tags `maven`
39 | or `gradle`. If it updates the documentation, label it as `documentation`.
40 | You can add both a release and a documentation label if needed.
41 | 5. You may squash and merge the pull request once you have the sign-off of two
42 | other developers. If you do not have permission to merge, you may request the
43 | second reviewer to merge the pull request for you.
44 |
45 | ## Code of conduct
46 |
47 | ### Our pledge
48 |
49 | In the interest of fostering an open and welcoming environment, we as
50 | contributors and maintainers pledge to make participation in our project and our
51 | community a harassment-free experience for everyone, regardless of age, body
52 | size, disability, ethnicity, gender identity and expression, level of
53 | experience, nationality, personal appearance, race, religion, or sexual identity
54 | and orientation.
55 |
56 | ### Our standards
57 |
58 | Examples of behavior that contribute to creating a positive environment include:
59 |
60 | - Using welcoming and inclusive language
61 | - Being respectful of differing viewpoints and experiences
62 | - Gracefully accepting constructive criticism
63 | - Focusing on what is best for the community
64 | - Showing empathy towards other community members
65 |
66 | Examples of unacceptable behavior by participants include:
67 |
68 | - The use of sexualized language or imagery and unwelcome sexual attention or
69 | advances
70 | - Trolling, insulting/derogatory comments, and personal or political attacks
71 | - Public or private harassment
72 | - Publishing others' private information, such as a physical or electronic
73 | address, without explicit permission
74 | - Other conduct which could reasonably be considered inappropriate in a
75 | professional setting
76 |
77 | ### Our responsibilities
78 |
79 | Project maintainers are responsible for clarifying the standards of acceptable
80 | behavior and are expected to take appropriate and fair corrective action in
81 | response to any instances of unacceptable behavior.
82 |
83 | Project maintainers have the right and responsibility to remove, edit, or reject
84 | comments, commits, code, wiki edits, issues, and other contributions that do not
85 | comply with this Code of Conduct, or to ban temporarily or permanently any
86 | contributor due to other behaviors that they deem inappropriate, threatening,
87 | offensive, or harmful.
88 |
89 | ### Scope
90 |
91 | This Code of conduct applies both within project spaces and in public spaces
92 | when an individual represents the project or its community. Examples of
93 | representing a project or community include using an official project email
94 | address, posting via an official social media account, or acting as an appointed
95 | representative at an online or offline event. Representation of a project may be
96 | further defined and clarified by project maintainers.
97 |
98 | ### Enforcement
99 |
100 | You can report incidents related to abusive, harassing, or otherwise
101 | unacceptable behavior by contacting the project team
102 | at [os3@sngular.com](mailto:os3@sngular.com). All complaints will be reviewed and
103 | investigated and will result in a response that is deemed necessary and
104 | appropriate to the circumstances. The project team is obligated to maintain
105 | confidentiality concerning the reporter of an incident. Further details of
106 | specific enforcement policies may be posted separately.
107 |
108 | Project maintainers who do not follow or enforce the Code of conduct in good
109 | faith may face temporary or permanent repercussions as determined by other
110 | members of the project's leadership.
111 |
112 | ### Attribution
113 |
114 | This Code of conduct has been adapted from the [Contributor Covenant][homepage],
115 | version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
116 | .
117 |
118 | [homepage]: http://contributor-covenant.org
119 |
120 | [version]: http://contributor-covenant.org/version/1/4/
121 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Pact DSL Builder
2 |
3 | [](https://app.codacy.com/gh/sngular/pact-annotation-processor/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)[](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor)
4 |
5 | This is a helper tool for Contract Testing with [Pact](https://docs.pact.io/).
6 | An annotation processor designed to generate DslPart objects for the body definitions based on annotations included in your model classes.
7 |
8 | The focus is to simplify JVM contract testing implementation, minimizing the amount of boilerplate code needed.
9 |
10 | Specially useful when defining body validations for interactions with complex models.
11 |
12 | ## Table of Contents
13 |
14 | - [Pact DSL Builder](#pact-dsl-builder)
15 | - [Getting Started](#getting-started)
16 | - [Requirements](#requirements)
17 | - [Compatibility with pact-jvm](#compatibility-with-pact-jvm)
18 | - [Configuration](#configuration)
19 | - [Usage](#usage)
20 | - [Annotations](#annotations)
21 | - [Builder](#builder)
22 | - [Roadmap](#roadmap)
23 | - [Contributing](#contributing)
24 | - [License](#license)
25 | - [Contact](#contact)
26 |
27 | ## Getting Started
28 |
29 | ### Requirements
30 |
31 | - JDK +17
32 |
33 | - Having inside your project a verification library of your choice to have the `@Max` and `@Min` annotations available, such as [Jakarta](https://central.sonatype.com/artifact/jakarta.validation/jakarta.validation-api), [Spring Boot](https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-starter-validation) or similar.
34 |
35 | ### Compatibility with pact-jvm
36 |
37 | | Pact DSL Builder | Pact JVM |
38 | |:------------------------------------------------------------------------------------:|:----------:|
39 | | [1.1.0](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor/1.1.0) | +4.6.3 |
40 | | [1.1.7](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor) | +4.6.3 |
41 | | [1.2.0](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor/1.1.0) | +4.6.3 |
42 | ### Configuration
43 |
44 | The only configuration needed for starting using the library is adding the dependency to your build automation tool:
45 |
46 | Maven
47 |
48 | ```xml
49 |
50 | ...
51 |
52 | com.sngular
53 | pact-annotation-processor
54 | 1.2.0
55 |
56 | ...
57 |
58 | ```
59 |
60 | Gradle
61 |
62 | ```groovy
63 | implementation('com.sngular:pact-annotation-processor:1.2.0')
64 | ```
65 |
66 | ## Usage
67 |
68 | To enable the code generation in a model class, you should annotate it as `@PactDslBodyBuilder`.
69 | That is the only requirement, all other annotations are optional and used for customising the generated code.
70 |
71 | ### Annotations
72 |
73 | We have developed 3 annotations to give support to your needs,
74 |
75 | - `@PactDslBodyBuilder` : To indicate which class you need to generate pact to.
76 | - `@Example`: To define constants values to set in your Pact Body.
77 | - `DslExclude`: To Exclude some property to be included in the builder.
78 |
79 | and support 2 standard Java annotations for validation
80 |
81 | - `@Min`: From Jakarta or Javax (or other validation tools) to indicate the
82 | minimum value to be cover for this property.
83 | - `@Max`: From Jakarta or Javax (or other validation tools) to indicate the
84 | maximum value to be cover for this property.
85 |
86 | | Annotation | Required | Level | Description |
87 | |----------------------:|:--------:|:-----:|:--------------------------------------------------------------------------------------------------------------------------------------------|
88 | | `@PactDslBodyBuilder` | true | Class | Main annotation, to be included in classes that want to be processed. |
89 | | `@Example` | false | Field | Used to provide an specific value for a field. If not present in a field, the value created will be random. |
90 | | `@Min` | false | Field | Defines the maximum value for numeric fields, or number of elements if applied to collections. Will be ignored if an `@Example` is present. |
91 | | `@Max` | false | Field | Defines the minimum value for numeric fields, or number of elements if applied to collections. Will be ignored if an `@Example` is present. |
92 | | `@DslExclude` | false | Field | Ignore de generation of example values. |
93 |
94 | > `@Example` values are always provided as String. If a specific format is
95 | required lets say for date
96 | > and datetime properties, then a format field should be provided,
97 | otherwise it will fall back to default
98 | > format. For date and datetime default format are:
99 | >
100 | > - `yyyy-MM-dd['['ZZZ']']` : for dates
101 | >
102 | > - `yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']` : for datetimes. Zone should be provided with this format.
103 |
104 | #### Example
105 |
106 | ```java
107 | package com.sngular.model;
108 |
109 | import com.sngular.annotation.pact.Example;
110 | import com.sngular.annotation.pact.PactDslBodyBuilder;
111 | import jakarta.validation.constraints.Max;
112 | import jakarta.validation.constraints.Min;
113 |
114 | import java.time.ZonedDateTime;
115 |
116 | @PactDslBodyBuilder
117 | public class Address {
118 |
119 | @Example("2023-12-03T10:15:30+01:00[Europe/Madrid]")
120 | private ZonedDateTime deliveryTime;
121 |
122 | @Example("2023-12-13")
123 | private Date creationDate;
124 |
125 | @Example("Jose")
126 | private String name;
127 |
128 | @Max(12)
129 | @Min(1)
130 | private int number;
131 |
132 | @Example("4")
133 | private long aLong;
134 |
135 | private ZonedDateTime init;
136 |
137 | private City city;
138 |
139 | }
140 | ```
141 |
142 | ### Builder
143 |
144 | Once the code is compiled, builder will be generated and available under `generated-sources` in your build directory.
145 |
146 | You will need to add the required import, and make use of the related builder class.
147 |
148 | #### Example
149 |
150 | ```java
151 | import com.sngular.model.AddressBuilder;
152 |
153 | AddressBuilder addressBuilder = new AddressBuilder();
154 | DslPart bodyDslPart = addressBuilder.build();
155 |
156 |
157 | @Pact(consumer = "consumer-poc", provider = "provider-poc")
158 | public RequestResponsePact getStudents(PactDslWithProvider builder) {
159 | AddressBuilder addressBuilder = new AddressBuilder();
160 | DslPart bodyDslPart = studentBuilder.build();
161 |
162 | return builder.given("Address exist")
163 | .uponReceiving("get all address")
164 | .path("/address/")
165 | .method("GET")
166 | .willRespondWith()
167 | .status(200)
168 | .headers(Map.of("Content-Type", "application/json"))
169 | .body(bodyDslPart)
170 | .toPact();
171 | }
172 | ```
173 |
174 | ## Notes
175 |
176 | - Dates: Regarding Timestamp and Date, we should use keep in mind the default
177 | formats will be used to parse those values:
178 | - For Dates, we are using `"yyyy-MM-dd['['ZZZ']']"` as default format
179 | - For Timestamps, we are using
180 | `"yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']"`
181 | as default format for datetime (ZonedDateTime)
182 | If you need and specific format the `@Example` support a format property
183 | to handle them.
184 |
185 | =======
186 |
187 | ### Expected Instance Builder
188 |
189 | In certain situations, especially when using the `@Example` annotation in all
190 | of your model data objects, you may prefer to perform classic manual
191 | instance creation for your validations in the `@Test` methods:
192 |
193 | ```java
194 | @Test
195 | @PactTestFor(pactMethod = "getAddressTest")
196 | void getAddressTest(MockServer mockServer) {
197 | RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();
198 | Address response = new BasicService(restTemplate).getAdress("...");
199 |
200 | // Manual instance creation for validation
201 | Address expectedAddress = new Address();
202 | expectedAddress.setName("Jose");
203 | expectedAddress.setNumber(12);
204 | // ...
205 |
206 | assertEquals(expectedAddress, response);
207 | }
208 | ```
209 |
210 | However, in many situations, especially when dealing with random values being generated,
211 | you may prefer to delegate the instance creation to the library itself.
212 | This is the purpose of the `buildExpectedInstance()` method, which generates an
213 | instance of the model object initialized with the values generated (or set
214 | by you with `@Example`) for the given object:
215 |
216 | ```java
217 |
218 | @Test
219 | @PactTestFor(pactMethod = "getAddressTest")
220 | void getAddressTest(MockServer mockServer) {
221 | RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();
222 | Address response = new BasicService(restTemplate).getAdress("...");
223 |
224 | // Using buildExpectedInstance() for instance creation
225 | Address expectedAddress = new AddressBuilder().buildExpectedInstance();
226 |
227 | assertEquals(expectedAddress, response);
228 | }
229 |
230 | ```
231 |
232 | ## Roadmap
233 |
234 | Roadmap available under [GitHub Projects section](https://github.com/orgs/sngular/projects/2).
235 |
236 | See the [open issues](https://github.com/sngular/pact-annotation-processor/issues) for a full list of proposed features (and known issues).
237 |
238 | ## Contributing
239 |
240 | Contributions are what makes the open source community special. Any contributions you make are greatly appreciated.
241 |
242 | If you have a suggestion that would make this library better,
243 | please [review our contributing guidelines](https://github.com/sngular/pact-annotation-processor/blob/main/CONTRIBUTING.md).
244 |
245 | Or you can simply [open a feature request issue](https://github.com/sngular/pact-annotation-processor/issues/new/choose).
246 |
247 | ## License
248 |
249 | Distributed under Mozilla Public License Version 2.0. See [LICENSE](https://github.com/sngular/pact-annotation-processor/blob/main/LICENSE) for more information
250 |
251 | ## Contact
252 |
253 | OS3 team: [os3@sngular.com](mailto:os3@sngular.com)
254 |
255 | Sngular - [GitHub Org](https://github.com/sngular)
256 |
257 |
258 |
--------------------------------------------------------------------------------
/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.sngular
6 | pact-annotation-processor
7 | 1.2.2
8 |
9 | PactDslBuilder - Annotation Processor
10 | Pact DSL Builder annotation processor.
11 | https://github.com/sngular/pactannotationprocessor
12 |
13 |
14 | Mozilla Public License 2.0
15 | https://github.com/sngular/pactannotationprocessor/blob/main/LICENSE
16 | repo
17 |
18 |
19 |
20 |
21 |
22 | jegarcia
23 | Jose Enrique Garcia Maciñeiras
24 | joseenrique.garcia@sngular.com
25 | https://sngular.github.io/
26 |
27 | Principal Engineer
28 | Team Leader
29 |
30 | Europe/Madrid
31 |
32 |
33 | ana.villa
34 | Ana Villa Caballero
35 | ana.villa@sngular.com
36 | https://sngular.github.io/
37 |
38 | Senior Developer
39 |
40 | Europe/Madrid
41 |
42 |
43 | apenlor
44 | Alejandro Pena Lorenzo
45 | alejandro.pena@sngular.com
46 | https://sngular.github.io/
47 |
48 | Principal Engineer
49 | Team Leader
50 |
51 | America/New_York
52 |
53 |
54 | tfdsimoes
55 | Tiago Filipe Domingues Simoes
56 | tfdsimoes+github@gmail.com
57 |
58 |
59 | Software Engineer
60 |
61 | Europe/Madrid
62 |
63 |
64 | MiguelSngularGithub
65 | Miguel Angel Escobar Perez
66 | miguel.escobar@sngular.com
67 |
68 |
69 | Software Engineer
70 |
71 | America/CDMX
72 |
73 |
74 |
75 |
76 | scm:git:git@github.com:sngular/pactannotationprocessorr.git
77 | scm:git:git@github.com:sngular/pactannotationprocessorr.git
78 | scm:git:git@github.com:sngular/pactannotationprocessorr.git
79 |
80 |
81 |
82 |
83 | ossrh
84 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
85 |
86 |
87 | ossrh
88 | https://s01.oss.sonatype.org/content/repositories/snapshots
89 |
90 |
91 |
92 |
93 | 17
94 | 17
95 | 2.3.32
96 | 1.18.30
97 | 3.13.0
98 | 1.1.1
99 | 4.6.3
100 | 20230618
101 | 2.3.4
102 | 4.1.95.Final
103 | 4.4
104 | 1.15
105 | 2.8.9
106 | 32.0.0-jre
107 | 3.3.0
108 | 3.6.0
109 | 3.0.0
110 | 1.5
111 |
112 | 3.24.2
113 | 5.9.2
114 | 5.3.1
115 |
116 |
117 |
118 |
119 | org.freemarker
120 | freemarker
121 | ${freemarker.version}
122 |
123 |
124 | org.projectlombok
125 | lombok
126 | ${projectlombok.version}
127 |
128 |
129 | org.apache.commons
130 | commons-lang3
131 | ${commons-lang3.version}
132 |
133 |
134 | com.google.auto.service
135 | auto-service
136 | ${google-auto.version}
137 | provided
138 |
139 |
140 | au.com.dius.pact
141 | consumer
142 | ${pact-consumer.version}
143 |
144 |
145 | commons-collections
146 | commons-collections
147 |
148 |
149 |
150 |
151 | org.apache.commons
152 | commons-collections4
153 | 4.4
154 |
155 |
156 | org.apache.commons
157 | commons-rng-simple
158 | ${apache-commons-rng.version}
159 |
160 |
161 | commons-codec
162 | commons-codec
163 | ${commons-codec.version}
164 |
165 |
166 | com.google.code.gson
167 | gson
168 | ${google-gson.version}
169 |
170 |
171 | com.google.guava
172 | guava
173 | ${google-guava.version}
174 |
175 |
176 |
177 | com.google.testing.compile
178 | compile-testing
179 | 0.21.0
180 | test
181 |
182 |
183 | org.assertj
184 | assertj-core
185 | ${assertj-core.version}
186 | test
187 |
188 |
189 | org.assertj
190 | assertj-core
191 |
192 |
193 |
194 |
195 | org.junit.jupiter
196 | junit-jupiter-engine
197 | ${junit-jupiter-engine.version}
198 | test
199 |
200 |
201 | org.junit.jupiter
202 | junit-jupiter-params
203 | ${junit-jupiter-engine.version}
204 | test
205 |
206 |
207 | org.mockito
208 | mockito-core
209 | ${mockito.version}
210 | test
211 |
212 |
213 | org.mockito
214 | mockito-junit-jupiter
215 | ${mockito.version}
216 | test
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 | org.apache.maven.plugins
225 | maven-checkstyle-plugin
226 | 3.3.0
227 |
228 | UTF-8
229 | UTF-8
230 | true
231 | true
232 | false
233 |
234 |
235 |
236 | com.puppycrawl.tools
237 | checkstyle
238 | 10.2
239 |
240 |
241 |
242 |
243 | com.github.ekryd.sortpom
244 | sortpom-maven-plugin
245 | ${sortpom-maven-plugin.version}
246 |
247 |
248 |
249 |
250 |
251 | org.apache.maven.plugins
252 | maven-surefire-plugin
253 | 3.1.2
254 |
255 |
256 | --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
257 | --add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
258 | --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
259 |
260 |
261 |
262 |
263 | default-test
264 |
265 | test
266 |
267 |
268 |
269 |
270 |
271 | org.apache.maven.plugins
272 | maven-checkstyle-plugin
273 |
274 | checkstyle.xml
275 |
276 |
277 |
278 | com.puppycrawl.tools
279 | checkstyle
280 | 10.2
281 |
282 |
283 |
284 |
285 | validate
286 |
287 | check
288 |
289 | validate
290 |
291 |
292 |
293 |
294 | org.apache.maven.plugins
295 | maven-compiler-plugin
296 | 3.11.0
297 |
298 |
299 | org.apache.maven.plugins
300 | maven-resources-plugin
301 | 3.3.1
302 |
303 |
304 | org.apache.maven.plugins
305 | maven-shade-plugin
306 | 3.5.0
307 |
308 | false
309 | true
310 | true
311 |
312 |
313 |
314 | make-shadow
315 |
316 | shade
317 |
318 | package
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | org.apache.maven.plugins
329 | maven-checkstyle-plugin
330 | 3.3.0
331 |
332 | ../checkstyle.xml
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 | production
341 |
342 |
343 | production
344 | true
345 |
346 |
347 |
348 |
349 |
350 | org.apache.maven.plugins
351 | maven-source-plugin
352 | ${maven-source-plugin.version}
353 |
354 |
355 | attach-sources
356 |
357 | jar
358 |
359 |
360 |
361 |
362 |
363 | org.apache.maven.plugins
364 | maven-javadoc-plugin
365 | ${maven-javadoc-plugin.version}
366 |
367 |
368 | attach-javadocs
369 |
370 | jar
371 |
372 |
373 |
374 |
375 |
376 | org.apache.maven.plugins
377 | maven-gpg-plugin
378 | 3.1.0
379 |
380 |
381 | sign-artifacts
382 |
383 | sign
384 |
385 | verify
386 |
387 |
388 | --pinentry-mode
389 | loopback
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/pact/DslExclude.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.pact;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Target(ElementType.FIELD)
9 | @Retention(RetentionPolicy.SOURCE)
10 | public @interface DslExclude {
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/pact/Example.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.pact;
8 |
9 | import java.lang.annotation.ElementType;
10 | import java.lang.annotation.Retention;
11 | import java.lang.annotation.RetentionPolicy;
12 | import java.lang.annotation.Target;
13 |
14 | @Target(ElementType.FIELD)
15 | @Retention(RetentionPolicy.SOURCE)
16 | public @interface Example {
17 |
18 | String value() default "";
19 |
20 | String format() default "";
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/pact/PactDslBodyBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.pact;
8 |
9 | import java.lang.annotation.ElementType;
10 | import java.lang.annotation.Retention;
11 | import java.lang.annotation.RetentionPolicy;
12 | import java.lang.annotation.Target;
13 |
14 | @Target(ElementType.TYPE)
15 | @Retention(RetentionPolicy.SOURCE)
16 | public @interface PactDslBodyBuilder {
17 |
18 | String[] customModifiers() default {};
19 |
20 | }
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/PactDslProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor;
8 |
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 | import java.util.Map;
13 | import java.util.Objects;
14 | import java.util.Optional;
15 | import java.util.Random;
16 | import java.util.Set;
17 |
18 | import javax.annotation.processing.AbstractProcessor;
19 | import javax.annotation.processing.Processor;
20 | import javax.annotation.processing.RoundEnvironment;
21 | import javax.annotation.processing.SupportedAnnotationTypes;
22 | import javax.lang.model.SourceVersion;
23 | import javax.lang.model.element.AnnotationMirror;
24 | import javax.lang.model.element.AnnotationValue;
25 | import javax.lang.model.element.Element;
26 | import javax.lang.model.element.ExecutableElement;
27 | import javax.lang.model.element.Name;
28 | import javax.lang.model.element.TypeElement;
29 | import javax.lang.model.type.DeclaredType;
30 | import javax.lang.model.util.Elements;
31 | import javax.lang.model.util.Types;
32 |
33 | import com.google.auto.service.AutoService;
34 | import com.google.common.collect.ImmutableMap;
35 | import com.sngular.annotation.pact.DslExclude;
36 | import com.sngular.annotation.pact.Example;
37 | import com.sngular.annotation.pact.PactDslBodyBuilder;
38 | import com.sngular.annotation.processor.exception.PactProcessorException;
39 | import com.sngular.annotation.processor.exception.TemplateFactoryException;
40 | import com.sngular.annotation.processor.exception.TemplateGenerationException;
41 | import com.sngular.annotation.processor.mapping.BigDecimalMapping;
42 | import com.sngular.annotation.processor.mapping.BigIntegerMapping;
43 | import com.sngular.annotation.processor.mapping.BooleanMapping;
44 | import com.sngular.annotation.processor.mapping.ByteMapping;
45 | import com.sngular.annotation.processor.mapping.CharMapping;
46 | import com.sngular.annotation.processor.mapping.DateMapping;
47 | import com.sngular.annotation.processor.mapping.DoubleMapping;
48 | import com.sngular.annotation.processor.mapping.FloatMapping;
49 | import com.sngular.annotation.processor.mapping.IntegerMapping;
50 | import com.sngular.annotation.processor.mapping.LongMapping;
51 | import com.sngular.annotation.processor.mapping.ShortMapping;
52 | import com.sngular.annotation.processor.mapping.StringMapping;
53 | import com.sngular.annotation.processor.mapping.TypeMapping;
54 | import com.sngular.annotation.processor.mapping.ZonedDateTimeMapping;
55 | import com.sngular.annotation.processor.model.ClassBuilderTemplate;
56 | import com.sngular.annotation.processor.model.DslComplexField;
57 | import com.sngular.annotation.processor.model.DslComplexTypeEnum;
58 | import com.sngular.annotation.processor.model.DslField;
59 | import com.sngular.annotation.processor.model.DslSimpleField;
60 | import com.sngular.annotation.processor.model.FieldValidations;
61 | import com.sngular.annotation.processor.template.ClasspathTemplateLoader;
62 | import com.sngular.annotation.processor.template.TemplateFactory;
63 | import freemarker.template.TemplateException;
64 | import lombok.extern.slf4j.Slf4j;
65 | import org.apache.commons.collections4.CollectionUtils;
66 | import org.apache.commons.collections4.IterableUtils;
67 | import org.apache.commons.collections4.IteratorUtils;
68 | import org.apache.commons.lang3.StringUtils;
69 | import org.apache.commons.lang3.math.NumberUtils;
70 | import org.apache.commons.rng.RestorableUniformRandomProvider;
71 | import org.apache.commons.rng.simple.RandomSource;
72 | import org.jetbrains.annotations.NotNull;
73 |
74 | @Slf4j
75 | @AutoService(Processor.class)
76 | @SupportedAnnotationTypes("com.sngular.annotation.pact.PactDslBodyBuilder")
77 | public class PactDslProcessor extends AbstractProcessor {
78 |
79 | static final Map> TYPE_MAPPING = ImmutableMap.>builder()
80 | .put("int", new IntegerMapping())
81 | .put("Integer", new IntegerMapping())
82 | .put("BigInteger", new BigIntegerMapping())
83 | .put("short", new ShortMapping())
84 | .put("Short", new ShortMapping())
85 | .put("byte", new ByteMapping())
86 | .put("Byte", new ByteMapping())
87 | .put("long", new LongMapping())
88 | .put("Long", new LongMapping())
89 | .put("char", new CharMapping())
90 | .put("Character", new CharMapping())
91 | .put("String", new StringMapping())
92 | .put("float", new FloatMapping())
93 | .put("Float", new FloatMapping())
94 | .put("double", new DoubleMapping())
95 | .put("Double", new DoubleMapping())
96 | .put("BigDecimal", new BigDecimalMapping())
97 | .put("boolean", new BooleanMapping())
98 | .put("Boolean", new BooleanMapping())
99 | .put("date", new DateMapping())
100 | .put("java.time.ZonedDateTime", new ZonedDateTimeMapping())
101 | .put("ZonedDateTime", new ZonedDateTimeMapping())
102 | .put("java.util.Date", new DateMapping())
103 | .put("Date", new DateMapping())
104 | .build();
105 |
106 | private static final String CUSTOM_MODIFIERS = "customModifiers";
107 |
108 | private Elements elementUtils;
109 |
110 | private Types typeUtils;
111 |
112 | private RestorableUniformRandomProvider randomSource = RandomSource.XO_RO_SHI_RO_128_PP.create();
113 |
114 | public PactDslProcessor() {
115 | }
116 |
117 | public PactDslProcessor(final RestorableUniformRandomProvider randomSource) {
118 | this.randomSource = randomSource;
119 | }
120 |
121 | @NotNull
122 | private static List extends Element> getFieldElements(final Element element) {
123 | return IterableUtils.toList(IterableUtils.filteredIterable(element.getEnclosedElements(), elt -> elt.getKind().isField()));
124 | }
125 |
126 | private static String getFormat(final Element fieldElement, final String defaultFormat) {
127 | final String value = fieldElement.getAnnotation(Example.class).format();
128 | return StringUtils.defaultIfEmpty(value, defaultFormat);
129 | }
130 |
131 | @Override
132 | public final SourceVersion getSupportedSourceVersion() {
133 | return SourceVersion.latestSupported();
134 | }
135 |
136 | @Override
137 | public final boolean process(final Set extends TypeElement> annotations, final RoundEnvironment roundEnv) {
138 |
139 | final TemplateFactory templateFactory;
140 | try {
141 | templateFactory = new TemplateFactory();
142 | } catch (final TemplateException e) {
143 | throw new TemplateFactoryException(e);
144 | }
145 | elementUtils = processingEnv.getElementUtils();
146 | typeUtils = processingEnv.getTypeUtils();
147 | final Set extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(PactDslBodyBuilder.class);
148 | IteratorUtils
149 | .transformedIterator(elementsAnnotatedWith.iterator(), this::composeBuilderTemplate).forEachRemaining(builderTemplate -> {
150 | try {
151 | final var builderFile = processingEnv.getFiler().createSourceFile(builderTemplate.completePath());
152 | templateFactory.writeTemplateToFile(ClasspathTemplateLoader.TEMPLATE_DSL_BUILDER, builderTemplate, builderFile.openWriter());
153 | } catch (IOException | TemplateException e) {
154 | throw new TemplateGenerationException("PactDslBodyBuilder", e);
155 | }
156 | });
157 | return true;
158 | }
159 |
160 | private ClassBuilderTemplate composeBuilderTemplate(final Element element) {
161 | final List extends Element> fieldElements = getFieldElements(element);
162 | final var qualifiedName = ((TypeElement) element).getQualifiedName().toString();
163 | String packageName = null;
164 | final int lastDot = qualifiedName.lastIndexOf('.');
165 | if (lastDot > 0) {
166 | packageName = qualifiedName.substring(0, lastDot);
167 | }
168 |
169 | final var builderSimpleClassName = qualifiedName.substring(lastDot + 1);
170 | final var builderClassName = builderSimpleClassName + "Builder";
171 | return ClassBuilderTemplate.builder()
172 | .fileName(builderClassName)
173 | .className(builderSimpleClassName)
174 | .modelPackage(packageName)
175 | .fieldList(getFields(fieldElements))
176 | .customModifiers(extractCustomModifiers(element))
177 | .build();
178 | }
179 |
180 | @NotNull
181 | private List getFields(final List extends Element> fieldElements) {
182 | return IterableUtils.toList(IterableUtils.transformedIterable(fieldElements, fieldElement -> composeDslField(fieldElement, false)));
183 | }
184 |
185 | private List getAnnotationValueAsType(final AnnotationMirror annotationMirror, final String key) {
186 | final var valueAsTypeList = new ArrayList();
187 | final var annotationValue = getAnnotationValue(annotationMirror, key);
188 | if (annotationValue != null) {
189 | valueAsTypeList.addAll(List.of(annotationValue.toString()
190 | .replace(" ", "").replace("{", "")
191 | .replace("}", "").replace("\"", "")
192 | .split(",")));
193 | }
194 | return valueAsTypeList;
195 | }
196 |
197 | private AnnotationValue getAnnotationValue(final AnnotationMirror annotationMirror, final String key) {
198 | AnnotationValue annotationValue = null;
199 | for (Map.Entry extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
200 | if (entry.getKey().getSimpleName().toString().equals(key)) {
201 | annotationValue = entry.getValue();
202 | }
203 | }
204 | return annotationValue;
205 | }
206 |
207 | private DslField composeDslField(final Element fieldElement, final boolean insideCollection) {
208 | final DslField result;
209 | final Optional> mappingOp = extractMappingByType(fieldElement);
210 | if (mappingOp.isEmpty()) {
211 | if (checkIfOwn(fieldElement)) {
212 | result = composeDslComplexField(fieldElement);
213 | } else {
214 | final String type = extractType(fieldElement);
215 | if (type.endsWith("List") || type.endsWith("Map") || type.endsWith("Set") || type.endsWith("Collection")) {
216 | result = composeCollection(fieldElement);
217 | } else {
218 | result = composeDslComplexField(fieldElement);
219 | }
220 | }
221 | } else {
222 | result = composeDslSimpleField(fieldElement, mappingOp.get(), insideCollection);
223 | }
224 | return result;
225 | }
226 |
227 | private DslComplexField composeDslComplexField(final Element element) {
228 | return DslComplexField.builder()
229 | .name(element.getSimpleName().toString())
230 | .fieldType(element.asType().toString())
231 | .needBuilder(checkIfOwn(element))
232 | .complexType(DslComplexTypeEnum.OBJECT)
233 | .fieldValidations(extractValidations(element))
234 | .empty(Objects.nonNull(element.getAnnotation(DslExclude.class)))
235 | .build();
236 | }
237 |
238 | private DslComplexField composeCollection(final Element element) {
239 | final var typeStr = cleanType(element);
240 | return DslComplexField.builder()
241 | .name(element.getSimpleName().toString())
242 | .fieldType(typeStr)
243 | .fields(extractTypes(element))
244 | .fieldValidations(extractValidations(element))
245 | .complexType(DslComplexTypeEnum.COLLECTION)
246 | .empty(Objects.nonNull(element.getAnnotation(DslExclude.class)))
247 | .build();
248 | }
249 |
250 | private boolean checkIfOwn(final Element element) {
251 | final var typePackage = elementUtils.getPackageOf(typeUtils.asElement(element.asType())).toString();
252 | final var parentType = elementUtils.getPackageOf(typeUtils.asElement(element.getEnclosingElement().asType())).toString();
253 | return parentType.equalsIgnoreCase(typePackage);
254 | }
255 |
256 | private String extractType(final Element element) {
257 | return ((TypeElement) typeUtils.asElement(element.asType())).getQualifiedName().toString();
258 | }
259 |
260 | private String cleanType(final Element element) {
261 | var finalType = element.asType().toString();
262 | for (var annotation : element.asType().getAnnotationMirrors()) {
263 | finalType = finalType.replace(annotation.toString(), "");
264 | }
265 | return finalType.replace(", ", "");
266 | }
267 |
268 | private FieldValidations extractValidations(final Element element) {
269 | final var validationBuilder = FieldValidations.builder();
270 |
271 | int minValue = 0;
272 | int maxValue = 0;
273 | final var type = element.asType();
274 | if (CollectionUtils.isNotEmpty(type.getAnnotationMirrors())) {
275 | for (var annotation : type.getAnnotationMirrors()) {
276 | if (annotation.getAnnotationType().toString().toUpperCase().endsWith("MAX")) {
277 | maxValue = ((Long) Objects.requireNonNull(getAnnotationValue(annotation, "value")).getValue()).intValue();
278 | validationBuilder.max(maxValue);
279 | } else {
280 | minValue = ((Long) Objects.requireNonNull(getAnnotationValue(annotation, "value")).getValue()).intValue();
281 | validationBuilder.min(minValue);
282 | }
283 | }
284 | //For random size calculation: defaults to +10 elements max if not defined.
285 | maxValue = (maxValue == 0) ? (minValue + 10) : maxValue;
286 | validationBuilder.randomSize(new Random().nextInt(maxValue - minValue + 1) + minValue);
287 | }
288 | return validationBuilder.build();
289 | }
290 |
291 | @NotNull
292 | private List extractTypes(final Element element) {
293 | final List listOfFields;
294 | final var listOfCustomMods = new ArrayList<>(CollectionUtils.collect(((DeclaredType) element.asType()).getTypeArguments(), typeUtils::asElement));
295 | if (listOfCustomMods.size() > 1) {
296 | listOfFields = new ArrayList<>(CollectionUtils.collect(listOfCustomMods, e -> composeDslField(e, true)));
297 | } else {
298 | listOfFields = List.of(
299 | composeDslSimpleField(listOfCustomMods.get(0),
300 | extractMappingByType(listOfCustomMods.get(0))
301 | .orElseThrow(() -> new PactProcessorException(listOfCustomMods.get(0).getSimpleName().toString())),
302 | true));
303 | }
304 | return listOfFields;
305 | }
306 |
307 | private List extractCustomModifiers(final Element element) {
308 | final List customModList = new ArrayList<>();
309 | final var listOfCustomMods = CollectionUtils.collect(element.getAnnotationMirrors(), a -> getAnnotationValueAsType(a, CUSTOM_MODIFIERS));
310 | CollectionUtils.collect(listOfCustomMods, customModList::addAll);
311 | return customModList;
312 | }
313 |
314 | private DslSimpleField composeDslSimpleField(final Element fieldElement, final TypeMapping> mapping, final boolean insideCollection) {
315 | final var validationBuilder = createValidationBuilder(fieldElement);
316 | final var simpleFieldBuilder = createSimpleFieldBuilder(fieldElement, mapping, insideCollection, validationBuilder);
317 |
318 | return simpleFieldBuilder.build();
319 | }
320 |
321 | private FieldValidations.FieldValidationsBuilder createValidationBuilder(final Element fieldElement) {
322 | final var validationBuilder = FieldValidations.builder();
323 |
324 | for (var annotation : fieldElement.asType().getAnnotationMirrors()) {
325 | if (annotation.getAnnotationType().toString().toUpperCase().endsWith("MAX")) {
326 | validationBuilder.max(((Long) Objects.requireNonNull(getAnnotationValue(annotation, "value")).getValue()).intValue());
327 | } else {
328 | validationBuilder.min(((Long) Objects.requireNonNull(getAnnotationValue(annotation, "value")).getValue()).intValue());
329 | }
330 | }
331 |
332 | return validationBuilder;
333 | }
334 |
335 | private DslSimpleField.DslSimpleFieldBuilder createSimpleFieldBuilder(final Element fieldElement, final TypeMapping> mapping,
336 | final boolean insideCollection, final FieldValidations.FieldValidationsBuilder validationBuilder) {
337 | final var simpleFieldBuilder = DslSimpleField.builder()
338 | .name(getNameOrNull(fieldElement.getSimpleName()))
339 | .fieldType(mapping.getFieldType())
340 | .functionByType(insideCollection ? mapping.getFunctionOnlyValue() : mapping.getFunctionType())
341 | .onlyValueFunction(insideCollection)
342 | .suffixValue(mapping.getSuffixValue())
343 | .formatValue(mapping.getFormatValue())
344 | .fieldValidations(validationBuilder.build())
345 | .empty(false);
346 |
347 | if (Objects.nonNull(fieldElement.getAnnotation(DslExclude.class))) {
348 | simpleFieldBuilder.empty(true);
349 | } else if (Objects.nonNull(fieldElement.getAnnotation(Example.class))) {
350 | simpleFieldBuilder.defaultValue(getDefaultValue(fieldElement, mapping.getFieldType()));
351 | simpleFieldBuilder.formatValue(getFormat(fieldElement, mapping.getFormatValue()));
352 | } else {
353 | simpleFieldBuilder.defaultValue(mapping.getRandomDefaultValue(validationBuilder.build(), randomSource));
354 | simpleFieldBuilder.formatValue(mapping.getFormatValue());
355 | }
356 |
357 | return simpleFieldBuilder;
358 | }
359 |
360 | private String getNameOrNull(final Name simpleName) {
361 | return simpleName.toString().matches("[A-Z].*") ? null : simpleName.toString();
362 | }
363 |
364 | private static Object getDefaultValue(final Element fieldElement, final String type) {
365 | final Object realValue;
366 | final String value = fieldElement.getAnnotation(Example.class).value();
367 | if (NumberUtils.isCreatable(value)) {
368 | realValue = switch (type) {
369 | case "int", "Integer" -> NumberUtils.toInt(value);
370 | case "BigInteger" -> NumberUtils.createBigInteger(value);
371 | case "long", "Long" -> NumberUtils.toLong(value);
372 | case "short", "Short" -> NumberUtils.toShort(value);
373 | case "byte", "Byte" -> NumberUtils.toByte(value);
374 | case "float", "Float" -> NumberUtils.toFloat(value);
375 | case "double", "Double" -> NumberUtils.toDouble(value);
376 | case "BigDecimal" -> NumberUtils.createBigDecimal(value);
377 | default -> throw new IllegalStateException("Unexpected value: " + type);
378 | };
379 | } else {
380 | realValue = value;
381 | }
382 | return realValue;
383 | }
384 |
385 | private Optional> extractMappingByType(final Element element) {
386 |
387 | final var type = element.asType();
388 | return switch (type.getKind()) {
389 | case BOOLEAN -> Optional.of(TYPE_MAPPING.get("boolean"));
390 | case BYTE -> Optional.of(TYPE_MAPPING.get("byte"));
391 | case SHORT -> Optional.of(TYPE_MAPPING.get("short"));
392 | case INT -> Optional.of(TYPE_MAPPING.get("int"));
393 | case LONG -> Optional.of(TYPE_MAPPING.get("long"));
394 | case CHAR -> Optional.of(TYPE_MAPPING.get("char"));
395 | case FLOAT -> Optional.of(TYPE_MAPPING.get("float"));
396 | case DOUBLE -> Optional.of(TYPE_MAPPING.get("double"));
397 | case DECLARED -> Optional.ofNullable(TYPE_MAPPING.get(this.typeUtils.asElement(type).getSimpleName().toString()));
398 | default -> Optional.empty();
399 | };
400 | }
401 |
402 | }
403 |
404 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/exception/PactProcessorException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.exception;
8 |
9 | public class PactProcessorException extends RuntimeException {
10 |
11 | private static final String ERROR_MESSAGE = "Error processing element %s";
12 |
13 | public PactProcessorException(final String ex) {
14 | super(String.format(ERROR_MESSAGE, ex));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/exception/TemplateFactoryException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.exception;
8 |
9 | public class TemplateFactoryException extends RuntimeException {
10 |
11 | private static final String ERROR_MESSAGE = "Error processing template factory";
12 |
13 | public TemplateFactoryException(final Exception ex) {
14 | super(ERROR_MESSAGE, ex);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/exception/TemplateGenerationException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.exception;
8 |
9 | public class TemplateGenerationException extends RuntimeException {
10 |
11 | private static final String ERROR_MESSAGE = "Error processing template builder for annotation %s";
12 |
13 | public TemplateGenerationException(final String annotationName, final Exception ex) {
14 | super(String.format(ERROR_MESSAGE, annotationName), ex);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/BigDecimalMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class BigDecimalMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "BigDecimal";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "decimalType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "decimalValue";
30 | }
31 |
32 | @Override
33 | public final Number getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final Number randomDefaultValue;
35 |
36 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
37 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), 0);
38 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), (int) Double.MAX_VALUE);
39 |
40 | randomDefaultValue = uniformRandomProvider.nextDouble(minValue, maxValue);
41 | } else {
42 | randomDefaultValue = uniformRandomProvider.nextDouble(Double.MIN_VALUE, Double.MAX_VALUE);
43 | }
44 |
45 | return randomDefaultValue;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/BigIntegerMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class BigIntegerMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "BigInteger";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "integerType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "integerValue";
30 | }
31 |
32 | @Override
33 | public final Integer getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final int randomDefaultValue;
35 |
36 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
37 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), Integer.MIN_VALUE);
38 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), Integer.MAX_VALUE);
39 |
40 | randomDefaultValue = uniformRandomProvider.nextInt(minValue, maxValue);
41 | } else {
42 | randomDefaultValue = uniformRandomProvider.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
43 | }
44 |
45 | return randomDefaultValue;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/BooleanMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import com.sngular.annotation.processor.model.FieldValidations;
10 | import org.apache.commons.rng.UniformRandomProvider;
11 | import org.apache.commons.rng.simple.RandomSource;
12 |
13 | public class BooleanMapping implements TypeMapping {
14 |
15 | private final UniformRandomProvider uniformRandomProvider = RandomSource.XO_RO_SHI_RO_128_PP.create();
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "boolean";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "booleanType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "booleanValue";
30 | }
31 |
32 | @Override
33 | public final Boolean getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | return uniformRandomProvider.nextBoolean();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/ByteMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class ByteMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "byte";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "integerType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "integerType";
30 | }
31 |
32 | @Override
33 | public final Integer getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final int result;
35 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
36 |
37 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), (int) Byte.MIN_VALUE);
38 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), (int) Byte.MAX_VALUE);
39 |
40 | result = uniformRandomProvider.nextInt(minValue, maxValue);
41 | } else {
42 | result = uniformRandomProvider.nextInt(Byte.MIN_VALUE, Byte.MAX_VALUE);
43 | }
44 |
45 | return result;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/CharMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import com.sngular.annotation.processor.model.FieldValidations;
10 | import org.apache.commons.lang3.RandomStringUtils;
11 | import org.apache.commons.rng.UniformRandomProvider;
12 |
13 | public class CharMapping implements TypeMapping {
14 |
15 | @Override
16 | public final String getFieldType() {
17 | return "char";
18 | }
19 |
20 | @Override
21 | public final String getFunctionType() {
22 | return "stringType";
23 | }
24 |
25 | @Override
26 | public final String getFunctionOnlyValue() {
27 | return "stringValue";
28 | }
29 |
30 | @Override
31 | public final String getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
32 | return RandomStringUtils.randomAlphanumeric(1);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/CustomDslModifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
10 |
11 | @FunctionalInterface
12 | public interface CustomDslModifier {
13 |
14 | PactDslJsonBody apply(final PactDslJsonBody pactDslJsonBody);
15 |
16 | }
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/DateMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.time.Instant;
10 | import java.util.Date;
11 |
12 | import com.sngular.annotation.processor.model.FieldValidations;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class DateMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "Date";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "date";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "dateValue";
30 | }
31 |
32 | @Override
33 | public final Date getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | return Date.from(Instant.now());
35 | }
36 |
37 | @Override
38 | public final String getFormatValue() {
39 | return "yyyy-MM-dd";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/DoubleMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class DoubleMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "double";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "decimalType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "decimalValue";
30 | }
31 |
32 | @Override
33 | public final Number getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final double result;
35 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
36 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), 0);
37 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), (int) Double.MAX_VALUE);
38 |
39 | result = uniformRandomProvider.nextDouble(minValue, maxValue);
40 | } else {
41 | result = uniformRandomProvider.nextDouble(0, Double.MAX_VALUE);
42 | }
43 |
44 | return result;
45 | }
46 |
47 | @Override
48 | public final String getSuffixValue() {
49 | return "D";
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/FloatMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class FloatMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "float";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "decimalType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "decimalValue";
30 | }
31 |
32 | @Override
33 | public final Number getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final Number randomDefaultValue;
35 |
36 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
37 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), 0);
38 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), (int) Float.MAX_VALUE);
39 |
40 | randomDefaultValue = uniformRandomProvider.nextDouble(minValue, maxValue);
41 | } else {
42 | randomDefaultValue = uniformRandomProvider.nextDouble(0, Float.MAX_VALUE);
43 | }
44 |
45 | return randomDefaultValue;
46 | }
47 |
48 | @Override
49 | public final String getSuffixValue() {
50 | return "F";
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/IntegerMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class IntegerMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "int";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "integerType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "integerValue";
30 | }
31 |
32 | @Override
33 | public final Integer getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final int result;
35 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
36 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), Integer.MIN_VALUE);
37 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), Integer.MAX_VALUE);
38 |
39 | result = uniformRandomProvider.nextInt(minValue, maxValue);
40 | } else {
41 | result = uniformRandomProvider.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
42 | }
43 | return result;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/LongMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class LongMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "long";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "integerType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "integerValue";
30 | }
31 |
32 | @Override
33 | public final Long getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final long result;
35 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
36 | final long minValue = Objects.nonNull(fieldValidations.getMin()) ? fieldValidations.getMin() : Long.MIN_VALUE;
37 | final long maxValue = Objects.nonNull(fieldValidations.getMax()) ? fieldValidations.getMax() : Long.MIN_VALUE;
38 |
39 | result = uniformRandomProvider.nextLong(minValue, maxValue);
40 | } else {
41 | result = uniformRandomProvider.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
42 | }
43 |
44 | return result;
45 | }
46 |
47 | @Override
48 | public final String getSuffixValue() {
49 | return "L";
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/ShortMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.rng.UniformRandomProvider;
14 |
15 | public class ShortMapping implements TypeMapping {
16 |
17 | @Override
18 | public final String getFieldType() {
19 | return "short";
20 | }
21 |
22 | @Override
23 | public final String getFunctionType() {
24 | return "integerType";
25 | }
26 |
27 | @Override
28 | public final String getFunctionOnlyValue() {
29 | return "integerValue";
30 | }
31 |
32 | @Override
33 | public final Integer getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
34 | final int result;
35 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
36 | final int minValue = ObjectUtils.defaultIfNull(fieldValidations.getMin(), (int) Short.MIN_VALUE);
37 | final int maxValue = ObjectUtils.defaultIfNull(fieldValidations.getMax(), (int) Short.MAX_VALUE);
38 |
39 | result = uniformRandomProvider.nextInt(minValue, maxValue);
40 | } else {
41 |
42 | result = uniformRandomProvider.nextInt(Short.MIN_VALUE, Short.MAX_VALUE);
43 | }
44 | return result;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/StringMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.util.Objects;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.lang3.ObjectUtils;
13 | import org.apache.commons.lang3.RandomStringUtils;
14 | import org.apache.commons.rng.UniformRandomProvider;
15 |
16 | public class StringMapping implements TypeMapping {
17 |
18 | public static final int DEFAULT_MAX = 15;
19 |
20 | public static final int DEFAULT_MIN = 1;
21 |
22 | @Override
23 | public final String getFieldType() {
24 | return "String";
25 | }
26 |
27 | @Override
28 | public final String getFunctionType() {
29 | return "stringType";
30 | }
31 |
32 | @Override
33 | public final String getFunctionOnlyValue() {
34 | return "stringValue";
35 | }
36 |
37 | @Override
38 | public final String getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
39 | final int length;
40 |
41 | if (Objects.nonNull(fieldValidations) && ObjectUtils.anyNotNull(fieldValidations.getMin(), fieldValidations.getMax())) {
42 | final int minLength = ObjectUtils.defaultIfNull(fieldValidations.getMin(), DEFAULT_MIN);
43 | final int maxLength = ObjectUtils.defaultIfNull(fieldValidations.getMax(), DEFAULT_MAX);
44 |
45 | length = uniformRandomProvider.nextInt(minLength, maxLength);
46 | } else {
47 | length = uniformRandomProvider.nextInt(DEFAULT_MIN, DEFAULT_MAX);
48 | }
49 |
50 | return RandomStringUtils.randomAlphanumeric(length);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/TypeMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import com.sngular.annotation.processor.model.FieldValidations;
10 | import org.apache.commons.rng.UniformRandomProvider;
11 |
12 | public interface TypeMapping {
13 |
14 | String getFieldType();
15 |
16 | String getFunctionType();
17 |
18 | String getFunctionOnlyValue();
19 |
20 | T getRandomDefaultValue(FieldValidations fieldValidations, UniformRandomProvider uniformRandomProvider);
21 |
22 | default String getSuffixValue() {
23 | return null;
24 | }
25 |
26 | default String getFormatValue() {
27 | return null;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/mapping/ZonedDateTimeMapping.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.mapping;
8 |
9 | import java.time.ZonedDateTime;
10 |
11 | import com.sngular.annotation.processor.model.FieldValidations;
12 | import org.apache.commons.rng.UniformRandomProvider;
13 |
14 | public class ZonedDateTimeMapping implements TypeMapping {
15 |
16 | @Override
17 | public final String getFieldType() {
18 | return "ZonedDateTime";
19 | }
20 |
21 | @Override
22 | public final String getFunctionType() {
23 | return "datetime";
24 | }
25 |
26 | @Override
27 | public final String getFunctionOnlyValue() {
28 | return "datetimeValue";
29 | }
30 |
31 | @Override
32 | public final ZonedDateTime getRandomDefaultValue(final FieldValidations fieldValidations, final UniformRandomProvider uniformRandomProvider) {
33 | return ZonedDateTime.now();
34 | }
35 |
36 | @Override
37 | public final String getFormatValue() {
38 | return "yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']";
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/ClassBuilderTemplate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | import java.util.List;
10 |
11 | import lombok.Builder;
12 | import lombok.Value;
13 |
14 | @Value
15 | @Builder
16 | public class ClassBuilderTemplate {
17 |
18 | String modelPackage;
19 |
20 | String fileName;
21 |
22 | String className;
23 |
24 | List fieldList;
25 |
26 | List customModifiers;
27 |
28 | public String completePath() {
29 | return String.format("%s.%s", modelPackage, fileName);
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/DslComplexField.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | import java.util.List;
10 |
11 | import lombok.Builder;
12 | import lombok.EqualsAndHashCode;
13 | import lombok.NonNull;
14 | import lombok.Value;
15 |
16 | @Value
17 | @EqualsAndHashCode(callSuper = true)
18 | public class DslComplexField extends DslField {
19 |
20 | @NonNull DslComplexTypeEnum complexType;
21 |
22 | List fields;
23 |
24 | String fieldType;
25 |
26 | FieldValidations fieldValidations;
27 |
28 | boolean needBuilder;
29 |
30 | boolean empty;
31 |
32 | @Builder
33 | private DslComplexField(
34 | final String name, @NonNull final DslComplexTypeEnum complexType, final List fields, final String fieldType, final FieldValidations fieldValidations,
35 | final boolean needBuilder, final boolean empty) {
36 | super(name);
37 | this.complexType = complexType;
38 | this.fields = fields;
39 | this.fieldType = fieldType;
40 | this.fieldValidations = fieldValidations;
41 | this.needBuilder = needBuilder;
42 | this.empty = empty;
43 | }
44 |
45 | public static class DslComplexFieldBuilder {}
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/DslComplexTypeEnum.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | public enum DslComplexTypeEnum {
10 | COLLECTION,
11 | OBJECT
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/DslField.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | import lombok.AllArgsConstructor;
10 | import lombok.Getter;
11 |
12 | @Getter
13 | @AllArgsConstructor
14 | public class DslField {
15 |
16 | private String name;
17 |
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/DslSimpleField.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | import lombok.Builder;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.Value;
12 |
13 | @Value
14 | @EqualsAndHashCode(callSuper = true)
15 | public class DslSimpleField extends DslField {
16 |
17 | String fieldType;
18 |
19 | String functionByType;
20 |
21 | Object defaultValue;
22 |
23 | String suffixValue;
24 |
25 | String formatValue;
26 |
27 | FieldValidations fieldValidations;
28 |
29 | boolean onlyValueFunction;
30 |
31 | boolean empty;
32 |
33 | @Builder
34 | private DslSimpleField(
35 | final String name, final String fieldType, final String functionByType, final Object defaultValue, final String suffixValue, final String formatValue,
36 | final FieldValidations fieldValidations,
37 | final boolean onlyValueFunction, final boolean empty) {
38 | super(name);
39 | this.fieldType = fieldType;
40 | this.functionByType = functionByType;
41 | this.defaultValue = defaultValue;
42 | this.suffixValue = suffixValue;
43 | this.formatValue = formatValue;
44 | this.fieldValidations = fieldValidations;
45 | this.onlyValueFunction = onlyValueFunction;
46 | this.empty = empty;
47 | }
48 |
49 | public static class DslSimpleFieldBuilder {}
50 | }
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/model/FieldValidations.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.model;
8 |
9 | import lombok.Builder;
10 | import lombok.Value;
11 |
12 | @Value
13 | @Builder
14 | public class FieldValidations {
15 |
16 | Integer min;
17 |
18 | Integer max;
19 |
20 | Integer randomSize;
21 |
22 | String regex;
23 |
24 | public static class FieldValidationsBuilder {}
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/template/ClasspathTemplateLoader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.template;
8 |
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.io.Reader;
12 | import java.io.StringReader;
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 | import java.util.Objects;
17 |
18 | import freemarker.cache.TemplateLoader;
19 |
20 | public class ClasspathTemplateLoader implements TemplateLoader {
21 |
22 | public static final String TEMPLATE_DSL_BUILDER = "templateDslBuilder.ftlh";
23 |
24 | private static final List TEMPLATE_FILES = List.of(TEMPLATE_DSL_BUILDER);
25 |
26 | private static final ClassLoader LOADER = ClasspathTemplateLoader.class.getClassLoader();
27 |
28 | private static final String TEMPLATES_PATH = "templates/";
29 |
30 | private final Map templatesMap = new HashMap<>();
31 |
32 | public ClasspathTemplateLoader() {
33 | templatesMap.putAll(getResourceFolderFiles());
34 | }
35 |
36 | private Map getResourceFolderFiles() {
37 | final Map templates = new HashMap<>();
38 | try {
39 | for (var templateFile : TEMPLATE_FILES) {
40 | templates.put(templateFile,
41 | readFile((InputStream) Objects.requireNonNull(LOADER.getResource(TEMPLATES_PATH + templateFile)).getContent()));
42 | }
43 | } catch (final IOException e) {
44 | e.printStackTrace();
45 | }
46 | return templates;
47 |
48 | }
49 |
50 | private String readFile(final InputStream file) throws IOException {
51 | return new String(file.readAllBytes());
52 | }
53 |
54 | @Override
55 | public final Object findTemplateSource(final String templateName) {
56 | return templatesMap.get(templateName);
57 | }
58 |
59 | @Override
60 | public final long getLastModified(final Object o) {
61 | return 0;
62 | }
63 |
64 | @Override
65 | public final Reader getReader(final Object template, final String charSet) {
66 | return new StringReader(template.toString());
67 | }
68 |
69 | @Override
70 | public void closeTemplateSource(final Object o) {
71 | // Not required to implement
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/sngular/annotation/processor/template/TemplateFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This Source Code Form is subject to the terms of the Mozilla Public
3 | * * License, v. 2.0. If a copy of the MPL was not distributed with this
4 | * * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5 | */
6 |
7 | package com.sngular.annotation.processor.template;
8 |
9 | import java.io.IOException;
10 | import java.io.Writer;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | import com.sngular.annotation.processor.model.ClassBuilderTemplate;
15 | import freemarker.template.Configuration;
16 | import freemarker.template.Template;
17 | import freemarker.template.TemplateException;
18 | import freemarker.template.TemplateExceptionHandler;
19 |
20 | public class TemplateFactory {
21 |
22 | private static final String SCHEMA_ROOT = "schema";
23 |
24 | private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_32);
25 |
26 | public TemplateFactory() throws TemplateException {
27 | cfg.setTemplateLoader(new ClasspathTemplateLoader());
28 | cfg.setDefaultEncoding("UTF-8");
29 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
30 | cfg.setLogTemplateExceptions(true);
31 | cfg.setSetting("c_format", "Java");
32 | }
33 |
34 | public final void writeTemplateToFile(final String templateName, final ClassBuilderTemplate classBuilder, final Writer writer) throws IOException, TemplateException {
35 | final Template template = cfg.getTemplate(templateName);
36 |
37 | final Map root = new HashMap<>();
38 | root.put(SCHEMA_ROOT, classBuilder);
39 | template.process(root, writer);
40 | writer.close();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/resources/templates/templateDslBuilder.ftlh:
--------------------------------------------------------------------------------
1 | <#assign constructor = false>
2 | <#macro writeAttrField field>
3 | <#if field.functionByType??>
4 | <#if field.fieldType == "boolean">
5 | ${field.fieldType} ${field.name} = ${field.defaultValue?string};
6 | <#elseif field.fieldType == "char">
7 | String ${field.name} = "${field.defaultValue}";
8 | <#elseif field.defaultValue?is_number>
9 | <#if field.fieldType == "BigInteger">
10 | BigInteger ${field.name} = new BigInteger("${field.defaultValue?c}");
11 | <#elseif field.fieldType == "BigDecimal">
12 | BigDecimal ${field.name} = new BigDecimal("${field.defaultValue?c}");
13 | <#else>
14 | ${field.fieldType} ${field.name} = ${field.defaultValue?c}<#if field.suffixValue?has_content>${field.suffixValue}#if>;
15 | #if>
16 | <#elseif field.defaultValue?is_boolean>
17 | ${field.fieldType} ${field.name} = ${field.defaultValue?then('true', 'false')};
18 | <#elseif field.functionByType == "date">
19 | <#assign constructor = true>
20 | ${field.fieldType} ${field.name} = new SimpleDateFormat("${field.formatValue?no_esc}").parse("${field.defaultValue?j_string?no_esc}");
21 | <#elseif field.functionByType == "datetime" && field.formatValue?has_content>
22 | ${field.fieldType} ${field.name} = ZonedDateTime.parse("${field.defaultValue?j_string?no_esc}", DateTimeFormatter.ofPattern("${field.formatValue?no_esc}"));
23 | <#elseif field.functionByType != "date" && field.functionByType != "datetime">
24 | ${field.fieldType} ${field.name} = "${field.defaultValue}";
25 | #if>
26 | <#else>
27 | <@writeComplexAttrField complexField=field/>
28 | #if>
29 | #macro>
30 |
31 | <#function writeRightValue value type format="">
32 | <#if value?is_number>
33 | <#return value?c/>
34 | <#elseif value?is_boolean>
35 | <#return value?then('true', 'false')/>
36 | <#elseif type == "dateValue">
37 | <#return 'Date.from(Instant.parse(\"${value?datetime?string.iso}\"))'?no_esc/>
38 | <#elseif type == "datetimeValue" && format?has_content>
39 | <#return 'ZonedDateTime.parse("${value?datetime}", DateTimeFormatter.ofPattern("${format?no_esc}")'?no_esc/>
40 | <#elseif type != "dateValue" && type != "datetimeValue">
41 | <#return '\"${value?j_string}\"'?no_esc/>
42 | #if>
43 | #function>
44 |
45 | <#macro writeSetterField field builderName>
46 | <#if field.functionByType??>
47 | <#if field.fieldType == "char">
48 | public ${builderName}Builder set${field.name?cap_first}(final String ${field.name}) {
49 | <#else>
50 | public ${builderName}Builder set${field.name?cap_first}(final ${field.fieldType?no_esc} ${field.name}) {
51 | #if>
52 | <#elseif field.complexType??>
53 | <#if field.complexType.name() == "COLLECTION">
54 | public ${builderName}Builder set${field.name?cap_first}(final ${field.fieldType?no_esc} ${field.name}) {
55 | <#elseif field.needBuilder>
56 | public ${builderName}Builder set${field.name?cap_first}(final ${field.fieldType?no_esc}Builder ${field.name}) {
57 | <#else >
58 | public ${builderName}Builder set${field.name?cap_first}(final ${field.fieldType?no_esc} ${field.name}) {
59 | #if>
60 | <#else>
61 | public ${builderName}Builder set${field.name?cap_first}(final ${field.fieldType?no_esc} ${field.name}) {
62 | #if>
63 | this.${field.name} = ${field.name};
64 | return this;
65 | }
66 | #macro>
67 |
68 | <#macro writeExpectedInstanceSetters field>
69 | <#if !field.empty>
70 | <#if field.fieldType == "char">
71 | object.set${field.name?cap_first}(this.${field.name}.charAt(0));
72 | <#else>
73 | object.set${field.name?cap_first}(this.${field.name});
74 | #if>
75 | #if>
76 | #macro>
77 |
78 | <#function writeDefaultsList fieldList>
79 | <#list fieldList as internalField>
80 | ${writeRightValue(internalField.defaultValue, internalField.functionByType, internalField.format)}<#if internalField?is_last>, #if>
81 | #list>
82 | #function>
83 |
84 | <#macro writeComplexAttrField complexField>
85 | <#if complexField.empty>
86 | <#-- Empty field there is the need to be initialized -->
87 | <#elseif complexField.complexType.name() == "COLLECTION">
88 | ${complexField.fieldType?no_esc} ${complexField.name} = List.of(${writeDefaultsList(complexField.fields)});
89 | <#elseif complexField.needBuilder>
90 | ${complexField.fieldType?no_esc}Builder ${complexField.name} = new ${complexField.fieldType?no_esc}Builder();
91 | <#else >
92 | ${complexField.fieldType?no_esc} ${complexField.name};
93 | #if>
94 | #macro>
95 |
96 | <#macro writeBuilderField field>
97 | <#if !field.empty>
98 | <#if field.functionByType??>
99 | <#if field.name?has_content>
100 | if (Objects.nonNull(${field.name})) {
101 | <#if field.formatValue??>
102 | <#if field.functionByType != "datetime">
103 | pactDslJsonBody.${field.functionByType}("${field.name}", "${field.formatValue?no_esc}", ${field.name});
104 | <#else>
105 | pactDslJsonBody.${field.functionByType}("${field.name}", "${field.formatValue?no_esc}", ${field.name}.toInstant());
106 | #if>
107 | <#elseif field.fieldType == "short">
108 | pactDslJsonBody.${field.functionByType}("${field.name}", (int) ${field.name});
109 | <#elseif field.fieldType == "BigInteger">
110 | pactDslJsonBody.${field.functionByType}("${field.name}", ${field.name}.intValue());
111 | <#elseif field.fieldType == "float">
112 | pactDslJsonBody.${field.functionByType}("${field.name}", (double) ${field.name});
113 | <#elseif field.fieldType == "byte">
114 | pactDslJsonBody.${field.functionByType}("${field.name}", (int) ${field.name});
115 | <#else>
116 | pactDslJsonBody.${field.functionByType}("${field.name}", ${field.name});
117 | #if>
118 | }
119 | <#else>
120 | <#if field.formatValue??>
121 | <#if field.functionByType == "dateValue">
122 | pactDslJsonBody.eachLike(PactDslJsonRootValue.date("${field.formatValue?no_esc}", Date.from(Instant.now())));
123 | <#elseif field.functionByType == "datetimeValue">
124 | pactDslJsonBody.eachLike(PactDslJsonRootValue.datetime("${field.formatValue?no_esc}", ZonedDateTime.now()));
125 | <#elseif field.functionByType == "integerValue">
126 | pactDslJsonBody.eachLike(PactDslJsonRootValue.integerMatching("${field.formatValue?no_esc}", ${field.defaultValue?int});
127 | <#elseif field.functionByType == "decimalValue">
128 | pactDslJsonBody.eachLike(PactDslJsonRootValue.decimalMatching("${field.formatValue?no_esc}", ${field.defaultValue?float});
129 | #if>
130 | #if>
131 | #if>
132 | #if>
133 | #if>
134 | #macro>
135 |
136 | <#macro writeBuilderLambdaField fieldList>
137 | PactDslJsonRootValue
138 | <#list fieldList as internalField>
139 | <#if internalField.functionByType??>
140 | <#if internalField.name?has_content>
141 | if (Objects.nonNull(${internalField.name})) {
142 | <#if internalField.formatValue??>
143 | <#if internalField.functionByType != "date" && internalField.functionByType != "datetime">
144 | .${internalField.functionByType}("${internalField.name}", "${internalField.formatValue?no_esc}", ${internalField.name})
145 | <#else>
146 | .${internalField.functionByType}("${internalField.name}", "${internalField.formatValue?no_esc}", ${internalField.name}.toInstant())
147 | #if>
148 | <#else>
149 | .${internalField.functionByType}("${internalField.name}", ${internalField.name})
150 | #if>
151 | }
152 | <#else>
153 | <#if internalField.formatValue??>
154 | <#if internalField.functionByType == "dateValue">
155 | .date("${internalField.formatValue?no_esc}", ${writeRightValue(internalField.defaultValue, internalField.functionByType)})
156 | <#elseif internalField.functionByType == "datetimeValue">
157 | .datetime("${internalField.formatValue?no_esc}", ${writeRightValue(internalField.defaultValue, internalField.functionByType)})
158 | <#elseif internalField.functionByType == "integerValue">
159 | .integerType("${internalField.formatValue?no_esc}",${writeRightValue(internalField.defaultValue, internalField.functionByType)})
160 | <#elseif internalField.functionByType == "decimalValue">
161 | .decimalType("${internalField.formatValue?no_esc}", ${writeRightValue(internalField.defaultValue, internalField.functionByType)})
162 | #if>
163 | <#elseif internalField.defaultValue?is_number>
164 | <#if internalField.functionByType == "dateValue">
165 | .date(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
166 | <#elseif internalField.functionByType == "datetimeValue">
167 | .datetime(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
168 | <#elseif internalField.functionByType == "integerValue">
169 | .integerType(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
170 | <#elseif internalField.functionByType == "decimalValue">
171 | .decimalType(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
172 | #if>
173 | <#elseif internalField.functionByType == "stringValue" >
174 | .stringType(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
175 | <#else >
176 | .${internalField.functionByType}(${writeRightValue(internalField.defaultValue, internalField.functionByType)})
177 | #if>
178 | #if>
179 | #if>
180 | #list>
181 | #macro>
182 |
183 | <#macro writeBuilderComplexField complexField>
184 | <#if !complexField.empty>
185 | <#if complexField.complexType.name() == "COLLECTION">
186 | <#if complexField.fieldValidations??>
187 | <#if complexField.fieldValidations.randomSize??>
188 | <#assign randomSize = "${complexField.fieldValidations.randomSize}"/>
189 | <#else >
190 | <#assign randomSize = ""/>
191 | #if>
192 | <#if complexField.fieldValidations.max??>
193 | <#assign max = "${complexField.fieldValidations.max}"/>
194 | <#else >
195 | <#assign max = ""/>
196 | #if>
197 | <#if complexField.fieldValidations.min??>
198 | <#assign min = "${complexField.fieldValidations.min}"/>
199 | <#else >
200 | <#assign min = ""/>
201 | #if>
202 | <#if max?has_content && min?has_content>
203 | if (${complexField.name}.isEmpty()) {
204 | pactDslJsonBody.minMaxArrayLike("${complexField.name}", ${min}, ${max});
205 | } else {
206 | pactDslJsonBody.minMaxArrayLike("${complexField.name}", ${min}, ${max}, <@writeBuilderLambdaField fieldList=complexField.fields/>, ${randomSize});
207 | }
208 | <#elseif min?has_content>
209 | if (${complexField.name}.isEmpty()) {
210 | pactDslJsonBody.minArrayLike("${complexField.name}", ${min});
211 | } else {
212 | pactDslJsonBody.minArrayLike("${complexField.name}", ${min}, <@writeBuilderLambdaField fieldList=complexField.fields/>, ${randomSize});
213 | }
214 | <#elseif max?has_content>
215 | if (${complexField.name}.isEmpty()) {
216 | pactDslJsonBody.maxArrayLike("${complexField.name}", ${max});
217 | } else {
218 | pactDslJsonBody.maxArrayLike("${complexField.name}", ${max}, <@writeBuilderLambdaField fieldList=complexField.fields/>, ${randomSize});
219 | }
220 | <#elseif complexField.empty>
221 | pactDslJsonBody.eachLike("${complexField.name}");
222 | <#else>
223 | pactDslJsonBody.eachLike("${complexField.name}", <@writeBuilderLambdaField fieldList=complexField.fields/>, 1);
224 | #if>
225 | <#else>
226 | pactDslJsonBody.array("${complexField.name}");
227 | <#list complexField.fields as internalField>
228 | <@writeBuilderField field=internalField/>
229 | #list>
230 | pactDslJsonBody.closeArray();
231 | #if>
232 | <#elseif complexField.needBuilder>
233 | pactDslJsonBody.object("${complexField.name}", ${complexField.name}.build());
234 | pactDslJsonBody.closeObject();
235 | <#else>
236 | <@writeBuilderField field=complexField/>
237 | #if>
238 | #if>
239 | #macro>
240 |
241 | package ${schema.modelPackage};
242 |
243 | import java.math.BigDecimal;
244 | import java.math.BigInteger;
245 | import java.text.DateFormat;
246 | import java.text.ParseException;
247 | import java.text.SimpleDateFormat;
248 | import java.time.Instant;
249 | import java.time.LocalDate;
250 | import java.time.ZonedDateTime;
251 | import java.time.format.DateTimeFormatter;
252 | import java.util.Date;
253 | import java.util.List;
254 | import java.util.Objects;
255 |
256 | import au.com.dius.pact.consumer.dsl.DslPart;
257 | import au.com.dius.pact.consumer.dsl.PactDslJsonArray;
258 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
259 | import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
260 | <#if schema.customModifiers??>
261 | import com.sngular.annotation.processor.mapping.CustomDslModifier;
262 | #if>
263 |
264 |
265 | import ${schema.modelPackage}.${schema.className};
266 |
267 | <#function complex(field)>
268 | <#return field.functionByType??>
269 | #function>
270 |
271 | <#function nocomplex(field)>
272 | <#if field.functionByType??>
273 | <#return false>
274 | <#else>
275 | <#return true>
276 | #if>
277 | #function>
278 |
279 | public class ${schema.className}Builder {
280 | <#list schema.fieldList as field>
281 | <#if !field.empty>
282 | <@writeAttrField field=field/>
283 | #if>
284 | #list>
285 |
286 | <#if constructor == true>
287 | public ${schema.className}Builder() throws ParseException {}
288 | #if>
289 |
290 | <#list schema.fieldList as field>
291 | <#if !field.empty>
292 | <@writeSetterField field=field builderName=schema.className?cap_first/>
293 | #if>
294 | #list>
295 |
296 | public DslPart build() {
297 | PactDslJsonBody pactDslJsonBody = new PactDslJsonBody();
298 | <#list schema.fieldList?filter(complex) as field>
299 | <@writeBuilderField field=field/>
300 | #list>
301 |
302 | <#list schema.fieldList?filter(nocomplex) as field>
303 | <@writeBuilderComplexField complexField=field />
304 | #list>
305 |
306 | <#-- if schema.customModifiers??>
307 | try {
308 | applyCustomModifiers(pactDslJsonBody);
309 | } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
310 | throw new RuntimeException(e);
311 | }
312 | #if -->
313 | return pactDslJsonBody;
314 | }
315 |
316 | public ${schema.className} buildExpectedInstance() {
317 | ${schema.className} object = new ${schema.className}();
318 | <#list schema.fieldList as field>
319 | <@writeExpectedInstanceSetters field=field/>
320 | #list>
321 | return object;
322 | }
323 |
324 | <#if schema.customModifiers??>
325 | private static void applyCustomModifiers(PactDslJsonBody pactDslJsonBody) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
326 | <#list schema.customModifiers as customMod>
327 | ((CustomDslModifier) Class.forName("${customMod}").newInstance()).apply(pactDslJsonBody);
328 | #list>
329 | }
330 | #if>
331 |
332 | }
333 |
334 |
--------------------------------------------------------------------------------
/src/test/java/com/sngular/annotation/processor/BasicDataTypeTest.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.processor;
2 |
3 | import static com.google.testing.compile.CompilationSubject.assertThat;
4 | import static com.google.testing.compile.Compiler.javac;
5 |
6 | import com.google.testing.compile.Compilation;
7 | import com.google.testing.compile.JavaFileObjects;
8 | import org.junit.jupiter.api.Test;
9 |
10 | public class BasicDataTypeTest {
11 |
12 | @Test
13 | public void characters() {
14 |
15 | Compilation compilation = javac().withProcessors(new PactDslProcessor()).compile(JavaFileObjects.forResource("basic/CharacterDataTypes.java"));
16 | assertThat(compilation).succeeded();
17 | assertThat(compilation).generatedSourceFile("com/sngular/resources/basic/CharacterDataTypesBuilder")
18 | .hasSourceEquivalentTo(JavaFileObjects.forResource("basic/CharacterDataTypesBuilder.java"));
19 | }
20 |
21 | @Test
22 | public void numbers() {
23 |
24 | Compilation compilation = javac().withProcessors(new PactDslProcessor()).compile(JavaFileObjects.forResource("basic/NumericDataTypes.java"));
25 | assertThat(compilation).succeeded();
26 | assertThat(compilation).generatedSourceFile("com/sngular/resources/basic/NumericDataTypesBuilder")
27 | .hasSourceEquivalentTo(JavaFileObjects.forResource("basic/NumericDataTypesBuilder.java"));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/sngular/annotation/processor/DateFormatTest.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.processor;
2 |
3 | import com.google.testing.compile.Compilation;
4 | import com.google.testing.compile.CompilationSubject;
5 | import com.google.testing.compile.Compiler;
6 | import com.google.testing.compile.JavaFileObjects;
7 | import org.junit.jupiter.api.Test;
8 |
9 | public class DateFormatTest {
10 |
11 | @Test
12 | public void basicDatesUsage() {
13 |
14 | Compilation compilation = Compiler.javac().withProcessors(new PactDslProcessor()).compile(JavaFileObjects.forResource("date/DateDataTypes.java"));
15 | CompilationSubject.assertThat(compilation).succeeded();
16 | CompilationSubject.assertThat(compilation).generatedSourceFile("com/sngular/annotation/examples/DateDataTypesBuilder")
17 | .hasSourceEquivalentTo(JavaFileObjects.forResource("date/DateDataTypesBuilder.java"));
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/com/sngular/annotation/processor/RandomValueGenerationTest.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.processor;
2 |
3 | import com.google.testing.compile.Compilation;
4 | import com.google.testing.compile.CompilationSubject;
5 | import com.google.testing.compile.Compiler;
6 | import com.google.testing.compile.JavaFileObjects;
7 | import org.apache.commons.rng.RestorableUniformRandomProvider;
8 | import org.junit.jupiter.api.Test;
9 | import org.mockito.Mockito;
10 |
11 | public class RandomValueGenerationTest {
12 |
13 | @Test
14 | public void numericDataTypes() {
15 | var theMock = Mockito.mock(RestorableUniformRandomProvider.class);
16 | Mockito.when(theMock.nextInt(0, Integer.MAX_VALUE)).thenReturn(18);
17 | Compilation compilation = Compiler.javac().withProcessors( new PactDslProcessor(theMock)).compile(JavaFileObjects.forResource("random/NumericDataTypes.java"));
18 | CompilationSubject.assertThat(compilation).succeeded();
19 | CompilationSubject.assertThat(compilation).generatedSourceFile("com/sngular/annotation/examples/NumericDataTypesBuilder")
20 | .hasSourceEquivalentTo(JavaFileObjects.forResource("random/NumericDataTypesBuilder.java"));
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/resources/basic/CharacterDataTypes.java:
--------------------------------------------------------------------------------
1 | package com.sngular.resources.basic;
2 |
3 | import com.sngular.annotation.pact.Example;
4 | import com.sngular.annotation.pact.PactDslBodyBuilder;
5 |
6 | @PactDslBodyBuilder
7 | public class CharacterDataTypes {
8 |
9 | @Example("nameExample")
10 | private String name;
11 |
12 | @Example("a")
13 | private char primitiveChar;
14 |
15 | @Example("b")
16 | private Character charObject;
17 |
18 | @Example("true")
19 | private boolean primitiveBoolean;
20 |
21 | @Example("false")
22 | private Boolean booleanObject;
23 |
24 | protected String getName() {
25 | return name;
26 | }
27 |
28 | protected void setName(final String name) {
29 | this.name = name;
30 | }
31 |
32 | public char getPrimitiveChar() {
33 | return primitiveChar;
34 | }
35 |
36 | public void setPrimitiveChar(char primitiveChar) {
37 | this.primitiveChar = primitiveChar;
38 | }
39 |
40 | public Character getCharObject() {
41 | return charObject;
42 | }
43 |
44 | public void setCharObject(Character charObject) {
45 | this.charObject = charObject;
46 | }
47 |
48 | public boolean isPrimitiveBoolean() {
49 | return primitiveBoolean;
50 | }
51 |
52 | public void setPrimitiveBoolean(boolean primitiveBoolean) {
53 | this.primitiveBoolean = primitiveBoolean;
54 | }
55 |
56 | public Boolean getBooleanObject() {
57 | return booleanObject;
58 | }
59 |
60 | public void setBooleanObject(Boolean booleanObject) {
61 | this.booleanObject = booleanObject;
62 | }
63 | }
--------------------------------------------------------------------------------
/src/test/resources/basic/CharacterDataTypesBuilder.java:
--------------------------------------------------------------------------------
1 | package com.sngular.resources.basic;
2 |
3 | import java.math.BigDecimal;
4 | import java.math.BigInteger;
5 | import java.text.DateFormat;
6 | import java.text.ParseException;
7 | import java.text.SimpleDateFormat;
8 | import java.time.Instant;
9 | import java.time.LocalDate;
10 | import java.time.ZonedDateTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.util.Date;
13 | import java.util.List;
14 | import java.util.Objects;
15 |
16 | import au.com.dius.pact.consumer.dsl.DslPart;
17 | import au.com.dius.pact.consumer.dsl.PactDslJsonArray;
18 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
19 | import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
20 | import com.sngular.annotation.processor.mapping.CustomDslModifier;
21 | import com.sngular.resources.basic.CharacterDataTypes;
22 |
23 | public class CharacterDataTypesBuilder {
24 | String name = "nameExample";
25 |
26 | String primitiveChar = "a";
27 |
28 | String charObject = "b";
29 |
30 | boolean primitiveBoolean = true;
31 |
32 | boolean booleanObject = false;
33 |
34 | public CharacterDataTypesBuilder setName(final String name) {
35 | this.name = name;
36 | return this;
37 | }
38 |
39 | public CharacterDataTypesBuilder setPrimitiveChar(final String primitiveChar) {
40 | this.primitiveChar = primitiveChar;
41 | return this;
42 | }
43 |
44 | public CharacterDataTypesBuilder setCharObject(final String charObject) {
45 | this.charObject = charObject;
46 | return this;
47 | }
48 |
49 | public CharacterDataTypesBuilder setPrimitiveBoolean(final boolean primitiveBoolean) {
50 | this.primitiveBoolean = primitiveBoolean;
51 | return this;
52 | }
53 |
54 | public CharacterDataTypesBuilder setBooleanObject(final boolean booleanObject) {
55 | this.booleanObject = booleanObject;
56 | return this;
57 | }
58 |
59 | public DslPart build() {
60 | PactDslJsonBody pactDslJsonBody = new PactDslJsonBody();
61 | if (Objects.nonNull(name)) {
62 | pactDslJsonBody.stringType("name", name);
63 | }
64 |
65 | if (Objects.nonNull(primitiveChar)) {
66 | pactDslJsonBody.stringType("primitiveChar", primitiveChar);
67 | }
68 |
69 | if (Objects.nonNull(charObject)) {
70 | pactDslJsonBody.stringType("charObject", charObject);
71 | }
72 |
73 | if (Objects.nonNull(primitiveBoolean)) {
74 | pactDslJsonBody.booleanType("primitiveBoolean", primitiveBoolean);
75 | }
76 |
77 | if (Objects.nonNull(booleanObject)) {
78 | pactDslJsonBody.booleanType("booleanObject", booleanObject);
79 | }
80 |
81 | return pactDslJsonBody;
82 | }
83 |
84 | public CharacterDataTypes buildExpectedInstance() {
85 | CharacterDataTypes object = new CharacterDataTypes();
86 | object.setName(this.name);
87 | object.setPrimitiveChar(this.primitiveChar.charAt(0));
88 | object.setCharObject(this.charObject.charAt(0));
89 | object.setPrimitiveBoolean(this.primitiveBoolean);
90 | object.setBooleanObject(this.booleanObject);
91 | return object;
92 | }
93 |
94 | private static void applyCustomModifiers(PactDslJsonBody pactDslJsonBody) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
95 | }
96 | }
97 |
98 |
--------------------------------------------------------------------------------
/src/test/resources/basic/NumericDataTypes.java:
--------------------------------------------------------------------------------
1 | package com.sngular.resources.basic;
2 |
3 | import com.sngular.annotation.pact.Example;
4 | import com.sngular.annotation.pact.PactDslBodyBuilder;
5 |
6 | import java.math.BigInteger;
7 | import java.math.BigDecimal;
8 |
9 | @PactDslBodyBuilder
10 | public class NumericDataTypes {
11 |
12 | @Example("10")
13 | private Integer integer;
14 |
15 | @Example("20")
16 | private int primitiveInt;
17 |
18 | @Example("30")
19 | private Long longObject;
20 |
21 | @Example("40")
22 | private long primitiveLong;
23 |
24 | @Example("50.1234")
25 | private Float floatObject;
26 |
27 | @Example("60.2345")
28 | private float primitiveFloat;
29 |
30 | @Example("70.3456")
31 | private Double doubleObject;
32 |
33 | @Example("80.4567")
34 | private double primitiveDouble;
35 |
36 | @Example("90")
37 | private Short shortObject;
38 |
39 | @Example("100")
40 | private short primitiveShort;
41 |
42 | @Example("110")
43 | private Byte byteObject;
44 |
45 | @Example("120")
46 | private byte primitiveByte;
47 |
48 | @Example("1303812548123548216")
49 | private BigInteger bigIntegerObject;
50 |
51 | @Example("1402354872534672834.2345")
52 | private BigDecimal bigDecimalObject;
53 |
54 | protected Integer getInteger() {
55 | return integer;
56 | }
57 |
58 | protected void setInteger(final Integer integer) {
59 | this.integer = integer;
60 | }
61 |
62 | protected int getPrimitiveInt() {
63 | return primitiveInt;
64 | }
65 |
66 | protected void setPrimitiveInt(final int primitiveInt) {
67 | this.primitiveInt = primitiveInt;
68 | }
69 |
70 | protected Long getLongObject() {
71 | return longObject;
72 | }
73 |
74 | protected void setLongObject(final Long longObject) {
75 | this.longObject = longObject;
76 | }
77 |
78 | protected long getPrimitiveLong() {
79 | return primitiveLong;
80 | }
81 |
82 | protected void setPrimitiveLong(final long primitiveLong) {
83 | this.primitiveLong = primitiveLong;
84 | }
85 |
86 | public Float getFloatObject() {
87 | return floatObject;
88 | }
89 |
90 | public void setFloatObject(Float floatObject) {
91 | this.floatObject = floatObject;
92 | }
93 |
94 | public float getPrimitiveFloat() {
95 | return primitiveFloat;
96 | }
97 |
98 | public void setPrimitiveFloat(float primitiveFloat) {
99 | this.primitiveFloat = primitiveFloat;
100 | }
101 |
102 | public Double getDoubleObject() {
103 | return doubleObject;
104 | }
105 |
106 | public void setDoubleObject(Double doubleObject) {
107 | this.doubleObject = doubleObject;
108 | }
109 |
110 | public double getPrimitiveDouble() {
111 | return primitiveDouble;
112 | }
113 |
114 | public void setPrimitiveDouble(double primitiveDouble) {
115 | this.primitiveDouble = primitiveDouble;
116 | }
117 |
118 | public Short getShortObject() {
119 | return shortObject;
120 | }
121 |
122 | public void setShortObject(Short shortObject) {
123 | this.shortObject = shortObject;
124 | }
125 |
126 | public short getPrimitiveShort() {
127 | return primitiveShort;
128 | }
129 |
130 | public void setPrimitiveShort(short primitiveShort) {
131 | this.primitiveShort = primitiveShort;
132 | }
133 |
134 | public Byte getByteObject() {
135 | return byteObject;
136 | }
137 |
138 | public void setByteObject(Byte byteObject) {
139 | this.byteObject = byteObject;
140 | }
141 |
142 | public byte getPrimitiveByte() {
143 | return primitiveByte;
144 | }
145 |
146 | public void setPrimitiveByte(byte primitiveByte) {
147 | this.primitiveByte = primitiveByte;
148 | }
149 |
150 | public BigInteger getBigIntegerObject() {
151 | return bigIntegerObject;
152 | }
153 |
154 | public void setBigIntegerObject(BigInteger bigIntegerObject) {
155 | this.bigIntegerObject = bigIntegerObject;
156 | }
157 |
158 | public BigDecimal getBigDecimalObject() {
159 | return bigDecimalObject;
160 | }
161 |
162 | public void setBigDecimalObject(BigDecimal bigDecimalObject) {
163 | this.bigDecimalObject = bigDecimalObject;
164 | }
165 | }
--------------------------------------------------------------------------------
/src/test/resources/basic/NumericDataTypesBuilder.java:
--------------------------------------------------------------------------------
1 | package com.sngular.resources.basic;
2 |
3 | import java.math.BigDecimal;
4 | import java.math.BigInteger;
5 | import java.text.DateFormat;
6 | import java.text.ParseException;
7 | import java.text.SimpleDateFormat;
8 | import java.time.Instant;
9 | import java.time.LocalDate;
10 | import java.time.ZonedDateTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.util.Date;
13 | import java.util.List;
14 | import java.util.Objects;
15 |
16 | import au.com.dius.pact.consumer.dsl.DslPart;
17 | import au.com.dius.pact.consumer.dsl.PactDslJsonArray;
18 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
19 | import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
20 | import com.sngular.annotation.processor.mapping.CustomDslModifier;
21 | import com.sngular.resources.basic.NumericDataTypes;
22 |
23 | public class NumericDataTypesBuilder {
24 |
25 | int integer = 10;
26 |
27 | int primitiveInt = 20;
28 |
29 | long longObject = 30L;
30 |
31 | long primitiveLong = 40L;
32 |
33 | float floatObject = 50.1234F;
34 |
35 | float primitiveFloat = 60.2345F;
36 |
37 | double doubleObject = 70.3456D;
38 |
39 | double primitiveDouble = 80.4567D;
40 |
41 | short shortObject = 90;
42 |
43 | short primitiveShort = 100;
44 |
45 | byte byteObject = 110;
46 |
47 | byte primitiveByte = 120;
48 |
49 | BigInteger bigIntegerObject = new BigInteger("1303812548123548216");
50 |
51 | BigDecimal bigDecimalObject = new BigDecimal("1402354872534672834.2345");
52 |
53 | public NumericDataTypesBuilder setInteger(final int integer) {
54 | this.integer = integer;
55 | return this;
56 | }
57 |
58 | public NumericDataTypesBuilder setPrimitiveInt(final int primitiveInt) {
59 | this.primitiveInt = primitiveInt;
60 | return this;
61 | }
62 |
63 | public NumericDataTypesBuilder setLongObject(final long longObject) {
64 | this.longObject = longObject;
65 | return this;
66 | }
67 |
68 | public NumericDataTypesBuilder setPrimitiveLong(final long primitiveLong) {
69 | this.primitiveLong = primitiveLong;
70 | return this;
71 | }
72 |
73 | public NumericDataTypesBuilder setFloatObject(final float floatObject) {
74 | this.floatObject = floatObject;
75 | return this;
76 | }
77 |
78 | public NumericDataTypesBuilder setPrimitiveFloat(final float primitiveFloat) {
79 | this.primitiveFloat = primitiveFloat;
80 | return this;
81 | }
82 |
83 | public NumericDataTypesBuilder setDoubleObject(final double doubleObject) {
84 | this.doubleObject = doubleObject;
85 | return this;
86 | }
87 |
88 | public NumericDataTypesBuilder setPrimitiveDouble(final double primitiveDouble) {
89 | this.primitiveDouble = primitiveDouble;
90 | return this;
91 | }
92 |
93 | public NumericDataTypesBuilder setShortObject(final short shortObject) {
94 | this.shortObject = shortObject;
95 | return this;
96 | }
97 |
98 | public NumericDataTypesBuilder setPrimitiveShort(final short primitiveShort) {
99 | this.primitiveShort = primitiveShort;
100 | return this;
101 | }
102 |
103 | public NumericDataTypesBuilder setByteObject(final byte byteObject) {
104 | this.byteObject = byteObject;
105 | return this;
106 | }
107 |
108 | public NumericDataTypesBuilder setPrimitiveByte(final byte primitiveByte) {
109 | this.primitiveByte = primitiveByte;
110 | return this;
111 | }
112 |
113 | public NumericDataTypesBuilder setBigIntegerObject(final BigInteger bigIntegerObject) {
114 | this.bigIntegerObject = bigIntegerObject;
115 | return this;
116 | }
117 |
118 | public NumericDataTypesBuilder setBigDecimalObject(final BigDecimal bigDecimalObject) {
119 | this.bigDecimalObject = bigDecimalObject;
120 | return this;
121 | }
122 |
123 | public DslPart build() {
124 | PactDslJsonBody pactDslJsonBody = new PactDslJsonBody();
125 | if (Objects.nonNull(integer)) {
126 | pactDslJsonBody.integerType("integer", integer);
127 | }
128 | if (Objects.nonNull(primitiveInt)) {
129 | pactDslJsonBody.integerType("primitiveInt", primitiveInt);
130 | }
131 | if (Objects.nonNull(longObject)) {
132 | pactDslJsonBody.integerType("longObject", longObject);
133 | }
134 | if (Objects.nonNull(primitiveLong)) {
135 | pactDslJsonBody.integerType("primitiveLong", primitiveLong);
136 | }
137 | if (Objects.nonNull(floatObject)) {
138 | pactDslJsonBody.decimalType("floatObject", (double) floatObject);
139 | }
140 |
141 | if (Objects.nonNull(primitiveFloat)) {
142 | pactDslJsonBody.decimalType("primitiveFloat", (double) primitiveFloat);
143 | }
144 |
145 | if (Objects.nonNull(doubleObject)) {
146 | pactDslJsonBody.decimalType("doubleObject", doubleObject);
147 | }
148 |
149 | if (Objects.nonNull(primitiveDouble)) {
150 | pactDslJsonBody.decimalType("primitiveDouble", primitiveDouble);
151 | }
152 |
153 | if (Objects.nonNull(shortObject)) {
154 | pactDslJsonBody.integerType("shortObject", (int) shortObject);
155 | }
156 |
157 | if (Objects.nonNull(primitiveShort)) {
158 | pactDslJsonBody.integerType("primitiveShort", (int) primitiveShort);
159 | }
160 |
161 | if (Objects.nonNull(byteObject)) {
162 | pactDslJsonBody.integerType("byteObject", (int) byteObject);
163 | }
164 |
165 | if (Objects.nonNull(primitiveByte)) {
166 | pactDslJsonBody.integerType("primitiveByte", (int) primitiveByte);
167 | }
168 |
169 | if (Objects.nonNull(bigIntegerObject)) {
170 | pactDslJsonBody.integerType("bigIntegerObject", bigIntegerObject.intValue());
171 | }
172 |
173 | if (Objects.nonNull(bigDecimalObject)) {
174 | pactDslJsonBody.decimalType("bigDecimalObject", bigDecimalObject);
175 | }
176 |
177 | return pactDslJsonBody;
178 | }
179 |
180 | public NumericDataTypes buildExpectedInstance() {
181 | NumericDataTypes object = new NumericDataTypes();
182 | object.setInteger(this.integer);
183 | object.setPrimitiveInt(this.primitiveInt);
184 | object.setLongObject(this.longObject);
185 | object.setPrimitiveLong(this.primitiveLong);
186 | object.setFloatObject(this.floatObject);
187 | object.setPrimitiveFloat(this.primitiveFloat);
188 | object.setDoubleObject(this.doubleObject);
189 | object.setPrimitiveDouble(this.primitiveDouble);
190 | object.setShortObject(this.shortObject);
191 | object.setPrimitiveShort(this.primitiveShort);
192 | object.setByteObject(this.byteObject);
193 | object.setPrimitiveByte(this.primitiveByte);
194 | object.setBigIntegerObject(this.bigIntegerObject);
195 | object.setBigDecimalObject(this.bigDecimalObject);
196 |
197 | return object;
198 | }
199 | private static void applyCustomModifiers(PactDslJsonBody pactDslJsonBody) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
200 | }
201 | }
--------------------------------------------------------------------------------
/src/test/resources/complex/NestedObjects.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sngular/pact-annotation-processor/5e906dbf9880f71663f74130319309772f070746/src/test/resources/complex/NestedObjects.java
--------------------------------------------------------------------------------
/src/test/resources/date/DateDataTypes.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.examples;
2 |
3 | import java.util.Date;
4 | import java.time.ZonedDateTime;
5 |
6 | import com.sngular.annotation.pact.Example;
7 | import com.sngular.annotation.pact.PactDslBodyBuilder;
8 |
9 | @PactDslBodyBuilder
10 | public class DateDataTypes {
11 |
12 | @Example(value = "23/04/2023 12:00", format = "dd/MM/yyyy HH:mm")
13 | private ZonedDateTime formattedZoneDateTime;
14 |
15 | @Example(value = "2023-12-03T10:15:30+01:00[Europe/Madrid]")
16 | private ZonedDateTime defaultFormatZoneDateTime;
17 |
18 | @Example(value = "2023-04-23")
19 | private Date defaultFormatDate;
20 |
21 | @Example(value = "23-04-2023", format = "dd-MM-yyyy")
22 | private Date formattedDate;
23 |
24 | protected ZonedDateTime getFormattedZoneDateTime() {
25 | return formattedZoneDateTime;
26 | }
27 |
28 | protected void setFormattedZoneDateTime(final ZonedDateTime formattedZoneDateTime) {
29 | this.formattedZoneDateTime = formattedZoneDateTime;
30 | }
31 |
32 | protected ZonedDateTime getDefaultFormatZoneDateTime() {
33 | return defaultFormatZoneDateTime;
34 | }
35 |
36 | protected void setDefaultFormatZoneDateTime(final ZonedDateTime defaultFormatZoneDateTime) {
37 | this.defaultFormatZoneDateTime = defaultFormatZoneDateTime;
38 | }
39 |
40 | protected Date getDefaultFormatDate() {
41 | return defaultFormatDate;
42 | }
43 |
44 | protected void setDefaultFormatDate(final Date defaultFormatDate) {
45 | this.defaultFormatDate = defaultFormatDate;
46 | }
47 |
48 | protected Date getFormattedDate() {
49 | return formattedDate;
50 | }
51 |
52 | protected void setFormattedDate(final Date formattedDate) {
53 | this.formattedDate = formattedDate;
54 | }
55 | }
--------------------------------------------------------------------------------
/src/test/resources/date/DateDataTypesBuilder.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.examples;
2 |
3 | import java.math.BigDecimal;
4 | import java.math.BigInteger;
5 | import java.text.DateFormat;
6 | import java.text.ParseException;
7 | import java.text.SimpleDateFormat;
8 | import java.time.Instant;
9 | import java.time.LocalDate;
10 | import java.time.ZonedDateTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.util.Date;
13 | import java.util.List;
14 | import java.util.Objects;
15 |
16 | import au.com.dius.pact.consumer.dsl.DslPart;
17 | import au.com.dius.pact.consumer.dsl.PactDslJsonArray;
18 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
19 | import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
20 | import com.sngular.annotation.processor.mapping.CustomDslModifier;
21 | import com.sngular.annotation.examples.DateDataTypes;
22 |
23 |
24 | public class DateDataTypesBuilder {
25 | ZonedDateTime formattedZoneDateTime = ZonedDateTime.parse("23/04/2023 12:00", DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
26 | ZonedDateTime defaultFormatZoneDateTime = ZonedDateTime.parse("2023-12-03T10:15:30+01:00[Europe/Madrid]", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']"));
27 | Date defaultFormatDate = new SimpleDateFormat("yyyy-MM-dd").parse("2023-04-23");
28 | Date formattedDate = new SimpleDateFormat("dd-MM-yyyy").parse("23-04-2023");
29 |
30 | public DateDataTypesBuilder() throws ParseException {}
31 |
32 | public DateDataTypesBuilder setFormattedZoneDateTime(final ZonedDateTime formattedZoneDateTime) {
33 | this.formattedZoneDateTime = formattedZoneDateTime;
34 | return this;
35 | }
36 | public DateDataTypesBuilder setDefaultFormatZoneDateTime(final ZonedDateTime defaultFormatZoneDateTime) {
37 | this.defaultFormatZoneDateTime = defaultFormatZoneDateTime;
38 | return this;
39 | }
40 | public DateDataTypesBuilder setDefaultFormatDate(final Date defaultFormatDate) {
41 | this.defaultFormatDate = defaultFormatDate;
42 | return this;
43 | }
44 | public DateDataTypesBuilder setFormattedDate(final Date formattedDate) {
45 | this.formattedDate = formattedDate;
46 | return this;
47 | }
48 |
49 | public DslPart build() {
50 | PactDslJsonBody pactDslJsonBody = new PactDslJsonBody();
51 | if (Objects.nonNull(formattedZoneDateTime)) {
52 | pactDslJsonBody.datetime("formattedZoneDateTime", "dd/MM/yyyy HH:mm", formattedZoneDateTime.toInstant());
53 | }
54 | if (Objects.nonNull(defaultFormatZoneDateTime)) {
55 | pactDslJsonBody.datetime("defaultFormatZoneDateTime", "yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']", defaultFormatZoneDateTime.toInstant());
56 | }
57 | if (Objects.nonNull(defaultFormatDate)) {
58 | pactDslJsonBody.date("defaultFormatDate", "yyyy-MM-dd", defaultFormatDate);
59 | }
60 | if (Objects.nonNull(formattedDate)) {
61 | pactDslJsonBody.date("formattedDate", "dd-MM-yyyy", formattedDate);
62 | }
63 |
64 | return pactDslJsonBody;
65 | }
66 | public DateDataTypes buildExpectedInstance() {
67 | DateDataTypes object = new DateDataTypes();
68 | object.setFormattedZoneDateTime(this.formattedZoneDateTime);
69 | object.setDefaultFormatZoneDateTime(this.defaultFormatZoneDateTime);
70 | object.setDefaultFormatDate(this.defaultFormatDate);
71 | object.setFormattedDate(this.formattedDate);
72 | return object;
73 | }
74 | private static void applyCustomModifiers(PactDslJsonBody pactDslJsonBody) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
75 | }
76 |
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/src/test/resources/random/NumericDataTypes.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.examples;
2 |
3 | import com.sngular.annotation.pact.Example;
4 | import com.sngular.annotation.pact.PactDslBodyBuilder;
5 |
6 | @PactDslBodyBuilder
7 | public class NumericDataTypes {
8 |
9 | private int age;
10 |
11 | protected int getAge() {
12 | return age;
13 | }
14 |
15 | protected void setAge(final int age) {
16 | this.age = age;
17 | }
18 | }
--------------------------------------------------------------------------------
/src/test/resources/random/NumericDataTypesBuilder.java:
--------------------------------------------------------------------------------
1 | package com.sngular.annotation.examples;
2 |
3 | import java.math.BigDecimal;
4 | import java.math.BigInteger;
5 | import java.text.DateFormat;
6 | import java.text.ParseException;
7 | import java.text.SimpleDateFormat;
8 | import java.time.Instant;
9 | import java.time.LocalDate;
10 | import java.time.ZonedDateTime;
11 | import java.time.format.DateTimeFormatter;
12 | import java.util.Date;
13 | import java.util.List;
14 | import java.util.Objects;
15 |
16 | import au.com.dius.pact.consumer.dsl.DslPart;
17 | import au.com.dius.pact.consumer.dsl.PactDslJsonArray;
18 | import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
19 | import au.com.dius.pact.consumer.dsl.PactDslJsonRootValue;
20 | import com.sngular.annotation.processor.mapping.CustomDslModifier;
21 | import com.sngular.annotation.examples.NumericDataTypes;
22 |
23 | public class NumericDataTypesBuilder {
24 | int age = 0;
25 |
26 | public NumericDataTypesBuilder setAge(final int age) {
27 | this.age = age;
28 | return this;
29 | }
30 |
31 | public DslPart build() {
32 | PactDslJsonBody pactDslJsonBody = new PactDslJsonBody();
33 | if (Objects.nonNull(age)) {
34 | pactDslJsonBody.integerType("age", age);
35 | }
36 |
37 | return pactDslJsonBody;
38 | }
39 | public NumericDataTypes buildExpectedInstance() {
40 | NumericDataTypes object = new NumericDataTypes();
41 | object.setAge(this.age);
42 | return object;
43 | }
44 | private static void applyCustomModifiers(PactDslJsonBody pactDslJsonBody) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
45 | }
46 |
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/styles/OS3_Style_idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | GETTERS_AND_SETTERS
217 | KEEP
218 |
219 |
220 | OVERRIDDEN_METHODS
221 | BY_NAME
222 |
223 |
224 | DEPENDENT_METHODS
225 | BREADTH_FIRST
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | true
234 | true
235 | true
236 | true
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 | true
246 | true
247 | true
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 | true
257 | true
258 | true
259 | true
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | true
269 | true
270 | true
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 | true
280 | true
281 | true
282 | true
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 | true
292 | true
293 | true
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 | true
303 | true
304 | true
305 | true
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 | true
315 | true
316 | true
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 | true
326 | true
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 | true
336 | true
337 | true
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 | true
347 | true
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 | true
357 | true
358 | true
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 | true
368 | true
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 | true
378 | true
379 | true
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 | true
389 | true
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 | true
399 | true
400 | true
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 | true
410 | true
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 | true
419 |
420 |
421 |
422 |
423 |
424 |
425 | true
426 |
427 |
428 |
429 |
430 |
431 |
432 | true
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 | true
441 | true
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 | true
450 |
451 |
452 |
453 |
454 |
455 |
456 | true
457 |
458 |
459 |
460 |
461 |
462 |
463 | true
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 | true
472 | true
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 | true
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 | xmlns:android
579 |
580 | ^$
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 | xmlns:.*
590 |
591 | ^$
592 |
593 |
594 | BY_NAME
595 |
596 |
597 |
598 |
599 |
600 |
601 | .*:id
602 |
603 | http://schemas.android.com/apk/res/android
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 | style
613 |
614 | ^$
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 | .*
624 |
625 | ^$
626 |
627 |
628 | BY_NAME
629 |
630 |
631 |
632 |
633 |
634 |
635 | .*:.*Style
636 |
637 | http://schemas.android.com/apk/res/android
638 |
639 |
640 | BY_NAME
641 |
642 |
643 |
644 |
645 |
646 |
647 | .*:layout_width
648 |
649 | http://schemas.android.com/apk/res/android
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 | .*:layout_height
659 |
660 | http://schemas.android.com/apk/res/android
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 | .*:layout_weight
670 |
671 | http://schemas.android.com/apk/res/android
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 | .*:layout_margin
681 |
682 | http://schemas.android.com/apk/res/android
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 | .*:layout_marginTop
692 |
693 | http://schemas.android.com/apk/res/android
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 | .*:layout_marginBottom
703 |
704 | http://schemas.android.com/apk/res/android
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 | .*:layout_marginStart
714 |
715 | http://schemas.android.com/apk/res/android
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 | .*:layout_marginEnd
725 |
726 | http://schemas.android.com/apk/res/android
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 | .*:layout_marginLeft
736 |
737 | http://schemas.android.com/apk/res/android
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 | .*:layout_marginRight
747 |
748 | http://schemas.android.com/apk/res/android
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 | .*:layout_.*
758 |
759 | http://schemas.android.com/apk/res/android
760 |
761 |
762 | BY_NAME
763 |
764 |
765 |
766 |
767 |
768 |
769 | .*:padding
770 |
771 | http://schemas.android.com/apk/res/android
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 | .*:paddingTop
781 |
782 | http://schemas.android.com/apk/res/android
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 | .*:paddingBottom
792 |
793 | http://schemas.android.com/apk/res/android
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 | .*:paddingStart
803 |
804 | http://schemas.android.com/apk/res/android
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 | .*:paddingEnd
814 |
815 | http://schemas.android.com/apk/res/android
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 | .*:paddingLeft
825 |
826 | http://schemas.android.com/apk/res/android
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 | .*:paddingRight
836 |
837 | http://schemas.android.com/apk/res/android
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 | .*
847 | http://schemas.android.com/apk/res/android
848 |
849 |
850 | BY_NAME
851 |
852 |
853 |
854 |
855 |
856 |
857 | .*
858 | http://schemas.android.com/apk/res-auto
859 |
860 |
861 | BY_NAME
862 |
863 |
864 |
865 |
866 |
867 |
868 | .*
869 | http://schemas.android.com/tools
870 |
871 |
872 | BY_NAME
873 |
874 |
875 |
876 |
877 |
878 |
879 | .*
880 | .*
881 |
882 |
883 | BY_NAME
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
--------------------------------------------------------------------------------