Compare commits
	
		
			51 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 009831f5db | |||
| 1bcdb1df8c | |||
| 7ae948bb79 | |||
| 29402fc27e | |||
| eca28292d5 | |||
| aef4cdabc3 | |||
| 04114aa0cf | |||
| 575102fbfa | |||
| 19fa13849e | |||
| 9ffebf1d1d | |||
| e35a1ae879 | |||
| 9c9cf85f92 | |||
| 1a2302f548 | |||
| 808784889b | |||
| f394254f38 | |||
| 0574d5da82 | |||
| 62435cd97e | |||
| d983210a10 | |||
| a704008f7d | |||
| 04a2014799 | |||
| b74b404e72 | |||
| 42245e026b | |||
| 284c00a88c | |||
| 0ae8f9ad16 | |||
| 7b31c66ce5 | |||
| fe63c6b954 | |||
| b4b6e40250 | |||
| 4d1f70a637 | |||
| 86dc0351fe | |||
| a049d3ca30 | |||
| c90af0bdc9 | |||
| f3ea7983df | |||
| ba314a97ed | |||
| c99fb84ef4 | |||
| eff5513705 | |||
| 66796d9591 | |||
| 554e2493aa | |||
| 49654698a6 | |||
| 61f3e70835 | |||
| 6ac2f1dcfc | |||
| 5b7fdce349 | |||
| 058fb2e640 | |||
| dfc7c77f47 | |||
| 1c82fb1a86 | |||
| 3b0c73bd55 | |||
| d9fcacc812 | |||
| 5fc45a23d3 | |||
| 81b6438a7c | |||
| 26ba20d964 | |||
| 659f9ca306 | |||
| 9f337db62c | 
| @@ -1,12 +1,12 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <classpath> | <classpath> | ||||||
| 	<classpathentry including="**/*.java" kind="src" output="out/maven/classes" path="src"> | 	<classpathentry including="**/*.java" kind="src" output="target/classes" path="src"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="optional" value="true"/> | 			<attribute name="optional" value="true"/> | ||||||
| 			<attribute name="maven.pomderived" value="true"/> | 			<attribute name="maven.pomderived" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
| 	<classpathentry kind="src" output="out/maven/test-classes" path="test/src"> | 	<classpathentry kind="src" output="target/test-classes" path="test/src"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="test" value="true"/> | 			<attribute name="test" value="true"/> | ||||||
| 			<attribute name="optional" value="true"/> | 			<attribute name="optional" value="true"/> | ||||||
| @@ -18,7 +18,7 @@ | |||||||
| 			<attribute name="maven.pomderived" value="true"/> | 			<attribute name="maven.pomderived" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
| 	<classpathentry excluding="**" kind="src" output="out/maven/test-classes" path="test/resources"> | 	<classpathentry excluding="**" kind="src" output="target/test-classes" path="test/resources"> | ||||||
| 		<attributes> | 		<attributes> | ||||||
| 			<attribute name="test" value="true"/> | 			<attribute name="test" value="true"/> | ||||||
| 			<attribute name="maven.pomderived" value="true"/> | 			<attribute name="maven.pomderived" value="true"/> | ||||||
| @@ -30,5 +30,5 @@ | |||||||
| 			<attribute name="maven.pomderived" value="true"/> | 			<attribute name="maven.pomderived" value="true"/> | ||||||
| 		</attributes> | 		</attributes> | ||||||
| 	</classpathentry> | 	</classpathentry> | ||||||
| 	<classpathentry kind="output" path="out/maven/classes"/> | 	<classpathentry kind="output" path="target/classes"/> | ||||||
| </classpath> | </classpath> | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | # To get started with Dependabot version updates, you'll need to specify which | ||||||
|  | # package ecosystems to update and where the package manifests are located. | ||||||
|  | # Please see the documentation for all configuration options: | ||||||
|  | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||||||
|  |  | ||||||
|  | version: 2 | ||||||
|  | updates: | ||||||
|  |   - package-ecosystem: "" # See documentation for possible values | ||||||
|  |     directory: "/" # Location of package manifests | ||||||
|  |     schedule: | ||||||
|  |       interval: "weekly" | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								.github/workflows/maven.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/maven.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time | ||||||
|  | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven | ||||||
|  |  | ||||||
|  | # This workflow uses actions that are not certified by GitHub. | ||||||
|  | # They are provided by a third-party and are governed by | ||||||
|  | # separate terms of service, privacy policy, and support | ||||||
|  | # documentation. | ||||||
|  |  | ||||||
|  | name: Java CI with Maven | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: [ "develop" ] | ||||||
|  |   pull_request: | ||||||
|  |     branches: [ "develop" ] | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |  | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |  | ||||||
|  |     steps: | ||||||
|  |     - uses: actions/checkout@v3 | ||||||
|  |     - name: Set up JDK 17 | ||||||
|  |       uses: actions/setup-java@v3 | ||||||
|  |       with: | ||||||
|  |         java-version: '21' | ||||||
|  |         distribution: 'temurin' | ||||||
|  |         cache: maven | ||||||
|  |     - name: Build with Maven | ||||||
|  |       run: mvn -B package --file pom.xml | ||||||
|  |     - name: find the element | ||||||
|  |       run: find . -name "dependency-graph.json" | ||||||
|  |  | ||||||
|  |     # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive | ||||||
|  |     - name: Update dependency graph | ||||||
|  |       uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 | ||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
| out/ | out/ | ||||||
|  | target/ | ||||||
| *.class | *.class | ||||||
| .settings/ | .settings/ | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.island/release.bash
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								.island/release.bash
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | mvn versions:set -DnewVersion=$(cat version.txt) | ||||||
|  |  | ||||||
							
								
								
									
										375
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										375
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,6 +1,373 @@ | |||||||
| PROPIETARY licence | Mozilla Public License Version 2.0 | ||||||
| ================== | ================================== | ||||||
|  |  | ||||||
| Copyright at Edouard DUPIN | 1. Definitions | ||||||
|  | -------------- | ||||||
|  |  | ||||||
| you have no right | 1.1. "Contributor" | ||||||
|  |     means each individual or legal entity that creates, contributes to | ||||||
|  |     the creation of, or owns Covered Software. | ||||||
|  |  | ||||||
|  | 1.2. "Contributor Version" | ||||||
|  |     means the combination of the Contributions of others (if any) used | ||||||
|  |     by a Contributor and that particular Contributor's Contribution. | ||||||
|  |  | ||||||
|  | 1.3. "Contribution" | ||||||
|  |     means Covered Software of a particular Contributor. | ||||||
|  |  | ||||||
|  | 1.4. "Covered Software" | ||||||
|  |     means Source Code Form to which the initial Contributor has attached | ||||||
|  |     the notice in Exhibit A, the Executable Form of such Source Code | ||||||
|  |     Form, and Modifications of such Source Code Form, in each case | ||||||
|  |     including portions thereof. | ||||||
|  |  | ||||||
|  | 1.5. "Incompatible With Secondary Licenses" | ||||||
|  |     means | ||||||
|  |  | ||||||
|  |     (a) that the initial Contributor has attached the notice described | ||||||
|  |         in Exhibit B to the Covered Software; or | ||||||
|  |  | ||||||
|  |     (b) that the Covered Software was made available under the terms of | ||||||
|  |         version 1.1 or earlier of the License, but not also under the | ||||||
|  |         terms of a Secondary License. | ||||||
|  |  | ||||||
|  | 1.6. "Executable Form" | ||||||
|  |     means any form of the work other than Source Code Form. | ||||||
|  |  | ||||||
|  | 1.7. "Larger Work" | ||||||
|  |     means a work that combines Covered Software with other material, in | ||||||
|  |     a separate file or files, that is not Covered Software. | ||||||
|  |  | ||||||
|  | 1.8. "License" | ||||||
|  |     means this document. | ||||||
|  |  | ||||||
|  | 1.9. "Licensable" | ||||||
|  |     means having the right to grant, to the maximum extent possible, | ||||||
|  |     whether at the time of the initial grant or subsequently, any and | ||||||
|  |     all of the rights conveyed by this License. | ||||||
|  |  | ||||||
|  | 1.10. "Modifications" | ||||||
|  |     means any of the following: | ||||||
|  |  | ||||||
|  |     (a) any file in Source Code Form that results from an addition to, | ||||||
|  |         deletion from, or modification of the contents of Covered | ||||||
|  |         Software; or | ||||||
|  |  | ||||||
|  |     (b) any new file in Source Code Form that contains any Covered | ||||||
|  |         Software. | ||||||
|  |  | ||||||
|  | 1.11. "Patent Claims" of a Contributor | ||||||
|  |     means any patent claim(s), including without limitation, method, | ||||||
|  |     process, and apparatus claims, in any patent Licensable by such | ||||||
|  |     Contributor that would be infringed, but for the grant of the | ||||||
|  |     License, by the making, using, selling, offering for sale, having | ||||||
|  |     made, import, or transfer of either its Contributions or its | ||||||
|  |     Contributor Version. | ||||||
|  |  | ||||||
|  | 1.12. "Secondary License" | ||||||
|  |     means either the GNU General Public License, Version 2.0, the GNU | ||||||
|  |     Lesser General Public License, Version 2.1, the GNU Affero General | ||||||
|  |     Public License, Version 3.0, or any later versions of those | ||||||
|  |     licenses. | ||||||
|  |  | ||||||
|  | 1.13. "Source Code Form" | ||||||
|  |     means the form of the work preferred for making modifications. | ||||||
|  |  | ||||||
|  | 1.14. "You" (or "Your") | ||||||
|  |     means an individual or a legal entity exercising rights under this | ||||||
|  |     License. For legal entities, "You" includes any entity that | ||||||
|  |     controls, is controlled by, or is under common control with You. For | ||||||
|  |     purposes of this definition, "control" means (a) the power, direct | ||||||
|  |     or indirect, to cause the direction or management of such entity, | ||||||
|  |     whether by contract or otherwise, or (b) ownership of more than | ||||||
|  |     fifty percent (50%) of the outstanding shares or beneficial | ||||||
|  |     ownership of such entity. | ||||||
|  |  | ||||||
|  | 2. License Grants and Conditions | ||||||
|  | -------------------------------- | ||||||
|  |  | ||||||
|  | 2.1. Grants | ||||||
|  |  | ||||||
|  | Each Contributor hereby grants You a world-wide, royalty-free, | ||||||
|  | non-exclusive license: | ||||||
|  |  | ||||||
|  | (a) under intellectual property rights (other than patent or trademark) | ||||||
|  |     Licensable by such Contributor to use, reproduce, make available, | ||||||
|  |     modify, display, perform, distribute, and otherwise exploit its | ||||||
|  |     Contributions, either on an unmodified basis, with Modifications, or | ||||||
|  |     as part of a Larger Work; and | ||||||
|  |  | ||||||
|  | (b) under Patent Claims of such Contributor to make, use, sell, offer | ||||||
|  |     for sale, have made, import, and otherwise transfer either its | ||||||
|  |     Contributions or its Contributor Version. | ||||||
|  |  | ||||||
|  | 2.2. Effective Date | ||||||
|  |  | ||||||
|  | The licenses granted in Section 2.1 with respect to any Contribution | ||||||
|  | become effective for each Contribution on the date the Contributor first | ||||||
|  | distributes such Contribution. | ||||||
|  |  | ||||||
|  | 2.3. Limitations on Grant Scope | ||||||
|  |  | ||||||
|  | The licenses granted in this Section 2 are the only rights granted under | ||||||
|  | this License. No additional rights or licenses will be implied from the | ||||||
|  | distribution or licensing of Covered Software under this License. | ||||||
|  | Notwithstanding Section 2.1(b) above, no patent license is granted by a | ||||||
|  | Contributor: | ||||||
|  |  | ||||||
|  | (a) for any code that a Contributor has removed from Covered Software; | ||||||
|  |     or | ||||||
|  |  | ||||||
|  | (b) for infringements caused by: (i) Your and any other third party's | ||||||
|  |     modifications of Covered Software, or (ii) the combination of its | ||||||
|  |     Contributions with other software (except as part of its Contributor | ||||||
|  |     Version); or | ||||||
|  |  | ||||||
|  | (c) under Patent Claims infringed by Covered Software in the absence of | ||||||
|  |     its Contributions. | ||||||
|  |  | ||||||
|  | This License does not grant any rights in the trademarks, service marks, | ||||||
|  | or logos of any Contributor (except as may be necessary to comply with | ||||||
|  | the notice requirements in Section 3.4). | ||||||
|  |  | ||||||
|  | 2.4. Subsequent Licenses | ||||||
|  |  | ||||||
|  | No Contributor makes additional grants as a result of Your choice to | ||||||
|  | distribute the Covered Software under a subsequent version of this | ||||||
|  | License (see Section 10.2) or under the terms of a Secondary License (if | ||||||
|  | permitted under the terms of Section 3.3). | ||||||
|  |  | ||||||
|  | 2.5. Representation | ||||||
|  |  | ||||||
|  | Each Contributor represents that the Contributor believes its | ||||||
|  | Contributions are its original creation(s) or it has sufficient rights | ||||||
|  | to grant the rights to its Contributions conveyed by this License. | ||||||
|  |  | ||||||
|  | 2.6. Fair Use | ||||||
|  |  | ||||||
|  | This License is not intended to limit any rights You have under | ||||||
|  | applicable copyright doctrines of fair use, fair dealing, or other | ||||||
|  | equivalents. | ||||||
|  |  | ||||||
|  | 2.7. Conditions | ||||||
|  |  | ||||||
|  | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted | ||||||
|  | in Section 2.1. | ||||||
|  |  | ||||||
|  | 3. Responsibilities | ||||||
|  | ------------------- | ||||||
|  |  | ||||||
|  | 3.1. Distribution of Source Form | ||||||
|  |  | ||||||
|  | All distribution of Covered Software in Source Code Form, including any | ||||||
|  | Modifications that You create or to which You contribute, must be under | ||||||
|  | the terms of this License. You must inform recipients that the Source | ||||||
|  | Code Form of the Covered Software is governed by the terms of this | ||||||
|  | License, and how they can obtain a copy of this License. You may not | ||||||
|  | attempt to alter or restrict the recipients' rights in the Source Code | ||||||
|  | Form. | ||||||
|  |  | ||||||
|  | 3.2. Distribution of Executable Form | ||||||
|  |  | ||||||
|  | If You distribute Covered Software in Executable Form then: | ||||||
|  |  | ||||||
|  | (a) such Covered Software must also be made available in Source Code | ||||||
|  |     Form, as described in Section 3.1, and You must inform recipients of | ||||||
|  |     the Executable Form how they can obtain a copy of such Source Code | ||||||
|  |     Form by reasonable means in a timely manner, at a charge no more | ||||||
|  |     than the cost of distribution to the recipient; and | ||||||
|  |  | ||||||
|  | (b) You may distribute such Executable Form under the terms of this | ||||||
|  |     License, or sublicense it under different terms, provided that the | ||||||
|  |     license for the Executable Form does not attempt to limit or alter | ||||||
|  |     the recipients' rights in the Source Code Form under this License. | ||||||
|  |  | ||||||
|  | 3.3. Distribution of a Larger Work | ||||||
|  |  | ||||||
|  | You may create and distribute a Larger Work under terms of Your choice, | ||||||
|  | provided that You also comply with the requirements of this License for | ||||||
|  | the Covered Software. If the Larger Work is a combination of Covered | ||||||
|  | Software with a work governed by one or more Secondary Licenses, and the | ||||||
|  | Covered Software is not Incompatible With Secondary Licenses, this | ||||||
|  | License permits You to additionally distribute such Covered Software | ||||||
|  | under the terms of such Secondary License(s), so that the recipient of | ||||||
|  | the Larger Work may, at their option, further distribute the Covered | ||||||
|  | Software under the terms of either this License or such Secondary | ||||||
|  | License(s). | ||||||
|  |  | ||||||
|  | 3.4. Notices | ||||||
|  |  | ||||||
|  | You may not remove or alter the substance of any license notices | ||||||
|  | (including copyright notices, patent notices, disclaimers of warranty, | ||||||
|  | or limitations of liability) contained within the Source Code Form of | ||||||
|  | the Covered Software, except that You may alter any license notices to | ||||||
|  | the extent required to remedy known factual inaccuracies. | ||||||
|  |  | ||||||
|  | 3.5. Application of Additional Terms | ||||||
|  |  | ||||||
|  | You may choose to offer, and to charge a fee for, warranty, support, | ||||||
|  | indemnity or liability obligations to one or more recipients of Covered | ||||||
|  | Software. However, You may do so only on Your own behalf, and not on | ||||||
|  | behalf of any Contributor. You must make it absolutely clear that any | ||||||
|  | such warranty, support, indemnity, or liability obligation is offered by | ||||||
|  | You alone, and You hereby agree to indemnify every Contributor for any | ||||||
|  | liability incurred by such Contributor as a result of warranty, support, | ||||||
|  | indemnity or liability terms You offer. You may include additional | ||||||
|  | disclaimers of warranty and limitations of liability specific to any | ||||||
|  | jurisdiction. | ||||||
|  |  | ||||||
|  | 4. Inability to Comply Due to Statute or Regulation | ||||||
|  | --------------------------------------------------- | ||||||
|  |  | ||||||
|  | If it is impossible for You to comply with any of the terms of this | ||||||
|  | License with respect to some or all of the Covered Software due to | ||||||
|  | statute, judicial order, or regulation then You must: (a) comply with | ||||||
|  | the terms of this License to the maximum extent possible; and (b) | ||||||
|  | describe the limitations and the code they affect. Such description must | ||||||
|  | be placed in a text file included with all distributions of the Covered | ||||||
|  | Software under this License. Except to the extent prohibited by statute | ||||||
|  | or regulation, such description must be sufficiently detailed for a | ||||||
|  | recipient of ordinary skill to be able to understand it. | ||||||
|  |  | ||||||
|  | 5. Termination | ||||||
|  | -------------- | ||||||
|  |  | ||||||
|  | 5.1. The rights granted under this License will terminate automatically | ||||||
|  | if You fail to comply with any of its terms. However, if You become | ||||||
|  | compliant, then the rights granted under this License from a particular | ||||||
|  | Contributor are reinstated (a) provisionally, unless and until such | ||||||
|  | Contributor explicitly and finally terminates Your grants, and (b) on an | ||||||
|  | ongoing basis, if such Contributor fails to notify You of the | ||||||
|  | non-compliance by some reasonable means prior to 60 days after You have | ||||||
|  | come back into compliance. Moreover, Your grants from a particular | ||||||
|  | Contributor are reinstated on an ongoing basis if such Contributor | ||||||
|  | notifies You of the non-compliance by some reasonable means, this is the | ||||||
|  | first time You have received notice of non-compliance with this License | ||||||
|  | from such Contributor, and You become compliant prior to 30 days after | ||||||
|  | Your receipt of the notice. | ||||||
|  |  | ||||||
|  | 5.2. If You initiate litigation against any entity by asserting a patent | ||||||
|  | infringement claim (excluding declaratory judgment actions, | ||||||
|  | counter-claims, and cross-claims) alleging that a Contributor Version | ||||||
|  | directly or indirectly infringes any patent, then the rights granted to | ||||||
|  | You by any and all Contributors for the Covered Software under Section | ||||||
|  | 2.1 of this License shall terminate. | ||||||
|  |  | ||||||
|  | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all | ||||||
|  | end user license agreements (excluding distributors and resellers) which | ||||||
|  | have been validly granted by You or Your distributors under this License | ||||||
|  | prior to termination shall survive termination. | ||||||
|  |  | ||||||
|  | ************************************************************************ | ||||||
|  | *                                                                      * | ||||||
|  | *  6. Disclaimer of Warranty                                           * | ||||||
|  | *  -------------------------                                           * | ||||||
|  | *                                                                      * | ||||||
|  | *  Covered Software is provided under this License on an "as is"       * | ||||||
|  | *  basis, without warranty of any kind, either expressed, implied, or  * | ||||||
|  | *  statutory, including, without limitation, warranties that the       * | ||||||
|  | *  Covered Software is free of defects, merchantable, fit for a        * | ||||||
|  | *  particular purpose or non-infringing. The entire risk as to the     * | ||||||
|  | *  quality and performance of the Covered Software is with You.        * | ||||||
|  | *  Should any Covered Software prove defective in any respect, You     * | ||||||
|  | *  (not any Contributor) assume the cost of any necessary servicing,   * | ||||||
|  | *  repair, or correction. This disclaimer of warranty constitutes an   * | ||||||
|  | *  essential part of this License. No use of any Covered Software is   * | ||||||
|  | *  authorized under this License except under this disclaimer.         * | ||||||
|  | *                                                                      * | ||||||
|  | ************************************************************************ | ||||||
|  |  | ||||||
|  | ************************************************************************ | ||||||
|  | *                                                                      * | ||||||
|  | *  7. Limitation of Liability                                          * | ||||||
|  | *  --------------------------                                          * | ||||||
|  | *                                                                      * | ||||||
|  | *  Under no circumstances and under no legal theory, whether tort      * | ||||||
|  | *  (including negligence), contract, or otherwise, shall any           * | ||||||
|  | *  Contributor, or anyone who distributes Covered Software as          * | ||||||
|  | *  permitted above, be liable to You for any direct, indirect,         * | ||||||
|  | *  special, incidental, or consequential damages of any character      * | ||||||
|  | *  including, without limitation, damages for lost profits, loss of    * | ||||||
|  | *  goodwill, work stoppage, computer failure or malfunction, or any    * | ||||||
|  | *  and all other commercial damages or losses, even if such party      * | ||||||
|  | *  shall have been informed of the possibility of such damages. This   * | ||||||
|  | *  limitation of liability shall not apply to liability for death or   * | ||||||
|  | *  personal injury resulting from such party's negligence to the       * | ||||||
|  | *  extent applicable law prohibits such limitation. Some               * | ||||||
|  | *  jurisdictions do not allow the exclusion or limitation of           * | ||||||
|  | *  incidental or consequential damages, so this exclusion and          * | ||||||
|  | *  limitation may not apply to You.                                    * | ||||||
|  | *                                                                      * | ||||||
|  | ************************************************************************ | ||||||
|  |  | ||||||
|  | 8. Litigation | ||||||
|  | ------------- | ||||||
|  |  | ||||||
|  | Any litigation relating to this License may be brought only in the | ||||||
|  | courts of a jurisdiction where the defendant maintains its principal | ||||||
|  | place of business and such litigation shall be governed by laws of that | ||||||
|  | jurisdiction, without reference to its conflict-of-law provisions. | ||||||
|  | Nothing in this Section shall prevent a party's ability to bring | ||||||
|  | cross-claims or counter-claims. | ||||||
|  |  | ||||||
|  | 9. Miscellaneous | ||||||
|  | ---------------- | ||||||
|  |  | ||||||
|  | This License represents the complete agreement concerning the subject | ||||||
|  | matter hereof. If any provision of this License is held to be | ||||||
|  | unenforceable, such provision shall be reformed only to the extent | ||||||
|  | necessary to make it enforceable. Any law or regulation which provides | ||||||
|  | that the language of a contract shall be construed against the drafter | ||||||
|  | shall not be used to construe this License against a Contributor. | ||||||
|  |  | ||||||
|  | 10. Versions of the License | ||||||
|  | --------------------------- | ||||||
|  |  | ||||||
|  | 10.1. New Versions | ||||||
|  |  | ||||||
|  | Mozilla Foundation is the license steward. Except as provided in Section | ||||||
|  | 10.3, no one other than the license steward has the right to modify or | ||||||
|  | publish new versions of this License. Each version will be given a | ||||||
|  | distinguishing version number. | ||||||
|  |  | ||||||
|  | 10.2. Effect of New Versions | ||||||
|  |  | ||||||
|  | You may distribute the Covered Software under the terms of the version | ||||||
|  | of the License under which You originally received the Covered Software, | ||||||
|  | or under the terms of any subsequent version published by the license | ||||||
|  | steward. | ||||||
|  |  | ||||||
|  | 10.3. Modified Versions | ||||||
|  |  | ||||||
|  | If you create software not governed by this License, and you want to | ||||||
|  | create a new license for such software, you may create and use a | ||||||
|  | modified version of this License if you rename the license and remove | ||||||
|  | any references to the name of the license steward (except to note that | ||||||
|  | such modified license differs from this License). | ||||||
|  |  | ||||||
|  | 10.4. Distributing Source Code Form that is Incompatible With Secondary | ||||||
|  | Licenses | ||||||
|  |  | ||||||
|  | If You choose to distribute Source Code Form that is Incompatible With | ||||||
|  | Secondary Licenses under the terms of this version of the License, the | ||||||
|  | notice described in Exhibit B of this License must be attached. | ||||||
|  |  | ||||||
|  | Exhibit A - Source Code Form License Notice | ||||||
|  | ------------------------------------------- | ||||||
|  |  | ||||||
|  |   This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  |   License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  |   file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  |  | ||||||
|  | If it is not possible or desirable to put the notice in a particular | ||||||
|  | file, then You may include the notice in a location (such as a LICENSE | ||||||
|  | file in a relevant directory) where a recipient would be likely to look | ||||||
|  | for such a notice. | ||||||
|  |  | ||||||
|  | You may add additional accurate notices of copyright ownership. | ||||||
|  |  | ||||||
|  | Exhibit B - "Incompatible With Secondary Licenses" Notice | ||||||
|  | --------------------------------------------------------- | ||||||
|  |  | ||||||
|  |   This Source Code Form is "Incompatible With Secondary Licenses", as | ||||||
|  |   defined by the Mozilla Public License, v. 2.0. | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,18 +1,60 @@ | |||||||
| Generic backend for archidata in java | Archi-data | ||||||
| =================================== | ========== | ||||||
|  |  | ||||||
|  | Archi-data is a framework that simplify: | ||||||
|  |   - Creating a REST server with: | ||||||
|  |     - Right control | ||||||
|  |     - Swagger display interface | ||||||
|  |     - Normalize error generate by the server | ||||||
|  |   - Access to the DB: | ||||||
|  |      - introspect Object and insert in the TD (SQLITE & MY-SQL) | ||||||
|  |      - Manage migration | ||||||
|  |   - JPA checker for many generic request | ||||||
|  |   - simplify the request of the Test-service | ||||||
|    |    | ||||||
|    |    | ||||||
|  | Develop in cmd-line: | ||||||
|  | -------------------- | ||||||
|  |  | ||||||
|  | The first step is configuring your JAVA version (or select the JVM with the OS) | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Install the dependency: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
| mvn install | mvn install | ||||||
|  | ``` | ||||||
|  |  | ||||||
| // create a single package jar | Run the test | ||||||
| mvn clean compile assembly:single | ```bash | ||||||
|  | mvn test | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Install it for external use | ||||||
|  | ```bash | ||||||
|  | mvn install | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Develop With Eclipse: | ||||||
|  | -------------------- | ||||||
|  |  | ||||||
| generic interface for all KAR web application | Import the project: | ||||||
|  |   - Open a (new) project on eclipse | ||||||
|  |   - `File` -> `Import` | ||||||
|  |     - `Maven` -> `Existing Maven project` | ||||||
|  |     - Select the `pom.xml` file and click on import | ||||||
|  |  | ||||||
|  | Run the Test: | ||||||
|  |   - Open the package `test.kar.archidata` | ||||||
|  |   - Click right on it | ||||||
|  |   - Select `Debug As` -> `JUnit Test` | ||||||
|  |  | ||||||
|  | Install in the local maven repository: | ||||||
|  |   - Click right on the `pom.xml` file | ||||||
|  |   - Select `Run As` -> `Maven install` | ||||||
|  |  | ||||||
|  |  | ||||||
| Somes tools: | Somes tools: | ||||||
| @@ -21,7 +63,7 @@ Somes tools: | |||||||
| Auto-update dependency: | Auto-update dependency: | ||||||
| ----------------------- | ----------------------- | ||||||
|  |  | ||||||
| auto-update to the last version dependency: | Auto-update to the last version dependency: | ||||||
|  |  | ||||||
| ```bash | ```bash | ||||||
| mvn versions:use-latest-versions | mvn versions:use-latest-versions | ||||||
| @@ -36,6 +78,22 @@ Simply run the cmd-line: | |||||||
| mvn formatter:format | mvn formatter:format | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | Reformat XML file like the pom.xml | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | XMLLINT_INDENT="	" xmllint  --format "back/pom.xml" -o "back/pom.xml" | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Enable the pre-commit checker | ||||||
|  | ----------------------------- | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | ./tools/configure_precommit.bash | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | > **_Note_**: You can change the code in `.git/hooks/pre-commit` by replacing `formatter:verify` with `formatter:format` to auto format the code @ every commit | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| Add Gitea in the dependency for the registry: | Add Gitea in the dependency for the registry: | ||||||
| ============================================= | ============================================= | ||||||
| @@ -65,8 +123,8 @@ edit file: ```~/.m2/settings.xml``` | |||||||
| release: | release: | ||||||
| ======== | ======== | ||||||
|  |  | ||||||
| ``` | ```bash | ||||||
| export PATH=/usr/lib/jvm/java-19-openjdk/bin:$PATH | export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH | ||||||
| mvn install | mvn install | ||||||
| mvn deploy | mvn deploy | ||||||
| ``` | ``` | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								dependabot.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								dependabot.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  |  | ||||||
							
								
								
									
										55
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -3,19 +3,16 @@ | |||||||
| 	<modelVersion>4.0.0</modelVersion> | 	<modelVersion>4.0.0</modelVersion> | ||||||
| 	<groupId>kangaroo-and-rabbit</groupId> | 	<groupId>kangaroo-and-rabbit</groupId> | ||||||
| 	<artifactId>archidata</artifactId> | 	<artifactId>archidata</artifactId> | ||||||
| 	<version>0.5.0</version> | 	<version>0.6.2</version> | ||||||
| 	<properties> | 	<properties> | ||||||
| 		<maven.compiler.version>3.1</maven.compiler.version> | 		<maven.compiler.version>3.1</maven.compiler.version> | ||||||
| 		<maven.compiler.source>21</maven.compiler.source> | 		<maven.compiler.source>21</maven.compiler.source> | ||||||
| 		<maven.compiler.target>21</maven.compiler.target> | 		<maven.compiler.target>21</maven.compiler.target> | ||||||
|  |  | ||||||
| 		<maven.dependency.version>3.1.1</maven.dependency.version> | 		<maven.dependency.version>3.1.1</maven.dependency.version> | ||||||
|  | 		<jersey.version>3.1.5</jersey.version> | ||||||
| 		<jersey.version>3.1.1</jersey.version> |  | ||||||
| 		<jaxb.version>2.3.1</jaxb.version> | 		<jaxb.version>2.3.1</jaxb.version> | ||||||
| 		<istack.version>4.1.1</istack.version> | 		<istack.version>4.1.1</istack.version> | ||||||
| 	</properties> | 	</properties> | ||||||
|  |  | ||||||
| 	<repositories> | 	<repositories> | ||||||
| 		<repository> | 		<repository> | ||||||
| 			<id>gitea</id> | 			<id>gitea</id> | ||||||
| @@ -32,7 +29,6 @@ | |||||||
| 			<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> | 			<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> | ||||||
| 		</snapshotRepository> | 		</snapshotRepository> | ||||||
| 	</distributionManagement> | 	</distributionManagement> | ||||||
|  |  | ||||||
| 	<dependencyManagement> | 	<dependencyManagement> | ||||||
| 		<dependencies> | 		<dependencies> | ||||||
| 			<dependency> | 			<dependency> | ||||||
| @@ -44,7 +40,6 @@ | |||||||
| 			</dependency> | 			</dependency> | ||||||
| 		</dependencies> | 		</dependencies> | ||||||
| 	</dependencyManagement> | 	</dependencyManagement> | ||||||
| 	 |  | ||||||
| 	<dependencies> | 	<dependencies> | ||||||
| 		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> | 		<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| @@ -112,7 +107,12 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>com.fasterxml.jackson.core</groupId> | 			<groupId>com.fasterxml.jackson.core</groupId> | ||||||
| 			<artifactId>jackson-databind</artifactId> | 			<artifactId>jackson-databind</artifactId> | ||||||
|             <version>2.16.0</version> | 			<version>2.16.1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.fasterxml.jackson.dataformat</groupId> | ||||||
|  | 			<artifactId>jackson-dataformat-csv</artifactId> | ||||||
|  | 			<version>2.16.1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>jakarta.servlet</groupId> | 			<groupId>jakarta.servlet</groupId> | ||||||
| @@ -129,7 +129,7 @@ | |||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.xerial</groupId> | 			<groupId>org.xerial</groupId> | ||||||
| 			<artifactId>sqlite-jdbc</artifactId> | 			<artifactId>sqlite-jdbc</artifactId> | ||||||
| 	        <version>3.44.1.0</version> | 			<version>3.40.0.0</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
| 		<!-- Interface for JWT token --> | 		<!-- Interface for JWT token --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| @@ -142,6 +142,12 @@ | |||||||
| 			<artifactId>jakarta.persistence-api</artifactId> | 			<artifactId>jakarta.persistence-api</artifactId> | ||||||
| 			<version>3.2.0-M1</version> | 			<version>3.2.0-M1</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- Swagger dependencies --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>io.swagger.core.v3</groupId> | ||||||
|  | 			<artifactId>swagger-jaxrs2-jakarta</artifactId> | ||||||
|  | 			<version>2.1.10</version> | ||||||
|  | 		</dependency> | ||||||
| 		<!-- | 		<!-- | ||||||
| 		************************************************************  | 		************************************************************  | ||||||
| 		** TEST dependency                                        ** | 		** TEST dependency                                        ** | ||||||
| @@ -159,12 +165,21 @@ | |||||||
| 			<version>5.10.1</version> | 			<version>5.10.1</version> | ||||||
| 	        <scope>test</scope> | 	        <scope>test</scope> | ||||||
| 	    </dependency> | 	    </dependency> | ||||||
|  | 	    <dependency> | ||||||
|  | 		    <groupId>net.revelc.code.formatter</groupId> | ||||||
|  | 		    <artifactId>formatter-maven-plugin</artifactId> | ||||||
|  | 		    <version>2.23.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 		    <groupId>org.apache.maven.plugins</groupId> | ||||||
|  | 		    <artifactId>maven-checkstyle-plugin</artifactId> | ||||||
|  | 		    <version>3.3.1</version> | ||||||
|  | 		</dependency> | ||||||
|     </dependencies> |     </dependencies> | ||||||
|  |  | ||||||
| 	<build> | 	<build> | ||||||
| 		<sourceDirectory>src</sourceDirectory> | 		<sourceDirectory>src</sourceDirectory> | ||||||
| 		<testSourceDirectory>test/src</testSourceDirectory> | 		<testSourceDirectory>test/src</testSourceDirectory> | ||||||
|     	<directory>${project.basedir}/out/maven/</directory> |  | ||||||
| 		<testResources> | 		<testResources> | ||||||
| 			<testResource> | 			<testResource> | ||||||
| 				<directory>${basedir}/test/resources</directory> | 				<directory>${basedir}/test/resources</directory> | ||||||
| @@ -185,6 +200,7 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-source-plugin</artifactId> | 				<artifactId>maven-source-plugin</artifactId> | ||||||
|  | 				<version>3.3.0</version> | ||||||
| 				<executions> | 				<executions> | ||||||
| 					<execution> | 					<execution> | ||||||
| 						<id>attach-sources</id> | 						<id>attach-sources</id> | ||||||
| @@ -194,6 +210,20 @@ | |||||||
| 					</execution> | 					</execution> | ||||||
| 				</executions> | 				</executions> | ||||||
| 			</plugin> | 			</plugin> | ||||||
|  | 			<!-- For dependabot plugin --> | ||||||
|  | 			<plugin> | ||||||
|  | 				<groupId>org.apache.servicemix.tooling</groupId> | ||||||
|  | 				<artifactId>depends-maven-plugin</artifactId> | ||||||
|  | 				<version>1.5.0</version> | ||||||
|  | 				<executions> | ||||||
|  | 					<execution> | ||||||
|  | 						<id>generate-depends-file</id> | ||||||
|  | 						<goals> | ||||||
|  | 							<goal>generate-depends-file</goal> | ||||||
|  | 						</goals> | ||||||
|  | 					</execution> | ||||||
|  | 				</executions> | ||||||
|  | 			</plugin> | ||||||
| 			<!-- junit results --> | 			<!-- junit results --> | ||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| @@ -227,7 +257,7 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> | 				<groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-checkstyle-plugin</artifactId> | 				<artifactId>maven-checkstyle-plugin</artifactId> | ||||||
| 				<version>3.1.0</version> | 		    	<version>3.3.1</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<configLocation>CheckStyle.xml</configLocation> | 					<configLocation>CheckStyle.xml</configLocation> | ||||||
| 					<consoleOutput>true</consoleOutput> | 					<consoleOutput>true</consoleOutput> | ||||||
| @@ -239,7 +269,7 @@ | |||||||
| 			<plugin> | 			<plugin> | ||||||
| 				<groupId>net.revelc.code.formatter</groupId> | 				<groupId>net.revelc.code.formatter</groupId> | ||||||
| 				<artifactId>formatter-maven-plugin</artifactId> | 				<artifactId>formatter-maven-plugin</artifactId> | ||||||
| 				<version>2.12.2</version> | 		    	<version>2.23.0</version> | ||||||
| 				<configuration> | 				<configuration> | ||||||
| 					<encoding>UTF-8</encoding> | 					<encoding>UTF-8</encoding> | ||||||
| 					<lineEnding>LF</lineEnding> | 					<lineEnding>LF</lineEnding> | ||||||
| @@ -278,5 +308,4 @@ | |||||||
| 			</plugin> | 			</plugin> | ||||||
| 		</plugins> | 		</plugins> | ||||||
| 	</reporting> | 	</reporting> | ||||||
|  |  | ||||||
| </project> | </project> | ||||||
|   | |||||||
| @@ -5,6 +5,9 @@ import java.sql.PreparedStatement; | |||||||
| import java.sql.SQLException; | import java.sql.SQLException; | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
|  | import org.kar.archidata.dataAccess.options.DBInterfaceOption; | ||||||
| import org.kar.archidata.db.DBEntry; | import org.kar.archidata.db.DBEntry; | ||||||
| import org.kar.archidata.model.User; | import org.kar.archidata.model.User; | ||||||
|  |  | ||||||
| @@ -12,21 +15,22 @@ public class UserDB { | |||||||
| 	 | 	 | ||||||
| 	public UserDB() {} | 	public UserDB() {} | ||||||
| 	 | 	 | ||||||
| 	public static User getUsers(final long userId) throws Exception { | 	public static User getUsers(final long userId, QueryOption... option) throws Exception { | ||||||
| 		return DataAccess.get(User.class, userId); | 		return DataAccess.get(User.class, userId, option); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static User getUserOrCreate(final long userId, final String userLogin) throws Exception { | 	public static User getUserOrCreate(final long userId, final String userLogin, QueryOption... option) throws Exception { | ||||||
| 		final User user = getUsers(userId); | 		final User user = getUsers(userId); | ||||||
| 		if (user != null) { | 		if (user != null) { | ||||||
| 			return user; | 			return user; | ||||||
| 		} | 		} | ||||||
| 		createUsersInfoFromOAuth(userId, userLogin); | 		createUsersInfoFromOAuth(userId, userLogin, option); | ||||||
| 		return getUsers(userId); | 		return getUsers(userId); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	private static void createUsersInfoFromOAuth(final long userId, final String login) throws IOException { | 	private static void createUsersInfoFromOAuth(final long userId, final String login, QueryOption... option) throws IOException { | ||||||
| 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); | 		QueryOptions options = new QueryOptions(option); | ||||||
|  | 		final DBEntry entry = DBInterfaceOption.getAutoEntry(options); | ||||||
| 		final String query = "INSERT INTO `user` (`id`, `login`, `lastConnection`, `admin`, `blocked`, `removed`) VALUE (?,?,now(3),'0','0','0')"; | 		final String query = "INSERT INTO `user` (`id`, `login`, `lastConnection`, `admin`, `blocked`, `removed`) VALUE (?,?,now(3),'0','0','0')"; | ||||||
| 		try { | 		try { | ||||||
| 			final PreparedStatement ps = entry.connection.prepareStatement(query); | 			final PreparedStatement ps = entry.connection.prepareStatement(query); | ||||||
|   | |||||||
| @@ -10,11 +10,18 @@ import org.kar.archidata.dataAccess.options.OverrideTableName; | |||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.GeneratedValue; | import jakarta.persistence.GeneratedValue; | ||||||
| import jakarta.persistence.GenerationType; | import jakarta.persistence.GenerationType; | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  | import jakarta.validation.constraints.Max; | ||||||
|  | import jakarta.validation.constraints.Min; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  | import jakarta.validation.constraints.Pattern; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
| public class AnnotationTools { | public class AnnotationTools { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(AnnotationTools.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(AnnotationTools.class); | ||||||
| @@ -45,10 +52,21 @@ public class AnnotationTools { | |||||||
| 		return tmp; | 		return tmp; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	public static String getSchemedescription(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Schema.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @Schema on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return ((Schema) annotation[0]).description(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	public static String getComment(final Field element) throws Exception { | 	public static String getComment(final Field element) throws Exception { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataComment.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataComment.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return null; | 			return getSchemedescription(element); | ||||||
| 		} | 		} | ||||||
| 		if (annotation.length > 1) { | 		if (annotation.length > 1) { | ||||||
| 			throw new Exception("Must not have more than 1 element @DataComment on " + element.getClass().getCanonicalName()); | 			throw new Exception("Must not have more than 1 element @DataComment on " + element.getClass().getCanonicalName()); | ||||||
| @@ -67,7 +85,51 @@ public class AnnotationTools { | |||||||
| 		return ((DataDefault) annotation[0]).value(); | 		return ((DataDefault) annotation[0]).value(); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static Integer getLimitSize(final Field element) throws Exception { | 	public static ManyToOne getManyToOne(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(ManyToOne.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @ManyToOne on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return (ManyToOne) annotation[0]; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static DataJson getDataJson(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(DataJson.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @ManyToOne on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return (DataJson) annotation[0]; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static Long getConstraintsMax(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Max.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @Size on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return ((Max) annotation[0]).value(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static Long getConstraintsMin(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Min.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @Size on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return ((Min) annotation[0]).value(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static int getLimitSize(final Field element) throws Exception { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return 255; | 			return 255; | ||||||
| @@ -76,7 +138,29 @@ public class AnnotationTools { | |||||||
| 			throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName()); | 			throw new Exception("Must not have more than 1 element @Column on " + element.getClass().getCanonicalName()); | ||||||
| 		} | 		} | ||||||
| 		final int length = ((Column) annotation[0]).length(); | 		final int length = ((Column) annotation[0]).length(); | ||||||
| 		return length <= 0 ? null : length; | 		return length <= 0 ? 0 : length; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static Size getConstraintsSize(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Size.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @Size on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return (Size) annotation[0]; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static String getConstraintsPattern(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Pattern.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @Pattern on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return ((Pattern) annotation[0]).regexp(); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) { | 	public static boolean isAnnotationGroup(final Field field, final Class<?> annotationType) { | ||||||
| @@ -117,7 +201,7 @@ public class AnnotationTools { | |||||||
| 		return name; | 		return name; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static boolean getNotNull(final Field element) throws Exception { | 	public static boolean getColumnNotNull(final Field element) throws Exception { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return false; | 			return false; | ||||||
| @@ -128,7 +212,26 @@ public class AnnotationTools { | |||||||
| 		return !((Column) annotation[0]).nullable(); | 		return !((Column) annotation[0]).nullable(); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	public static boolean getConstraintsNotNull(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(NotNull.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		if (annotation.length > 1) { | ||||||
|  | 			throw new Exception("Must not have more than 1 element @NotNull on " + element.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	public static boolean isPrimaryKey(final Field element) throws Exception { | 	public static boolean isPrimaryKey(final Field element) throws Exception { | ||||||
|  | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Id.class); | ||||||
|  | 		if (annotation.length == 0) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static boolean isUnique(final Field element) throws Exception { | ||||||
| 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | 		final Annotation[] annotation = element.getDeclaredAnnotationsByType(Column.class); | ||||||
| 		if (annotation.length == 0) { | 		if (annotation.length == 0) { | ||||||
| 			return false; | 			return false; | ||||||
| @@ -245,7 +348,7 @@ public class AnnotationTools { | |||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static boolean isGenericField(final Field elem) throws Exception { | 	public static boolean isGenericField(final Field elem) throws Exception { | ||||||
| 		return AnnotationTools.isPrimaryKey(elem) || AnnotationTools.isCreatedAtField(elem) || AnnotationTools.isUpdateAtField(elem); | 		return AnnotationTools.isPrimaryKey(elem) || AnnotationTools.isCreatedAtField(elem) || AnnotationTools.isUpdateAtField(elem) || AnnotationTools.isDeletedField(elem); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public static Field getFieldOfId(final Class<?> clazz) throws Exception { | 	public static Field getFieldOfId(final Class<?> clazz) throws Exception { | ||||||
| @@ -261,4 +364,17 @@ public class AnnotationTools { | |||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	public static Field getFieldNamed(final Class<?> clazz, final String name) throws Exception { | ||||||
|  | 		for (final Field field : clazz.getFields()) { | ||||||
|  | 			// static field is only for internal global declaration ==> remove it .. | ||||||
|  | 			if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (AnnotationTools.getFieldName(field).equals(name)) { | ||||||
|  | 				return field; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,8 +7,7 @@ import java.lang.annotation.Target; | |||||||
|  |  | ||||||
| @Target({ ElementType.TYPE, ElementType.FIELD }) | @Target({ ElementType.TYPE, ElementType.FIELD }) | ||||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @Deprecated(since = "0.5.2") | ||||||
| public @interface DataComment { | public @interface DataComment { | ||||||
|  |  | ||||||
| 	String value(); | 	String value(); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,6 +5,11 @@ import java.lang.annotation.Retention; | |||||||
| import java.lang.annotation.RetentionPolicy; | import java.lang.annotation.RetentionPolicy; | ||||||
| import java.lang.annotation.Target; | import java.lang.annotation.Target; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunctionInterface; | ||||||
|  | import org.kar.archidata.dataAccess.options.CheckFunctionVoid; | ||||||
|  |  | ||||||
| @Target({ ElementType.TYPE, ElementType.FIELD }) | @Target({ ElementType.TYPE, ElementType.FIELD }) | ||||||
| @Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||||
| public @interface DataJson {} | public @interface DataJson { | ||||||
|  | 	Class<? extends CheckFunctionInterface> checker() default CheckFunctionVoid.class; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -24,12 +24,14 @@ import org.glassfish.jersey.media.multipart.FormDataParam; | |||||||
| import org.kar.archidata.annotation.security.PermitTokenInURI; | import org.kar.archidata.annotation.security.PermitTokenInURI; | ||||||
| import org.kar.archidata.dataAccess.DataAccess; | import org.kar.archidata.dataAccess.DataAccess; | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; | import org.kar.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.kar.archidata.dataAccess.options.Condition; | ||||||
| import org.kar.archidata.filter.GenericContext; | import org.kar.archidata.filter.GenericContext; | ||||||
| import org.kar.archidata.model.Data; | import org.kar.archidata.model.Data; | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import jakarta.annotation.security.RolesAllowed; | import jakarta.annotation.security.RolesAllowed; | ||||||
| import jakarta.ws.rs.Consumes; | import jakarta.ws.rs.Consumes; | ||||||
| import jakarta.ws.rs.GET; | import jakarta.ws.rs.GET; | ||||||
| @@ -94,7 +96,7 @@ public class DataResource { | |||||||
| 	public static Data getWithSha512(final String sha512) { | 	public static Data getWithSha512(final String sha512) { | ||||||
| 		LOGGER.info("find sha512 = {}", sha512); | 		LOGGER.info("find sha512 = {}", sha512); | ||||||
| 		try { | 		try { | ||||||
| 			return DataAccess.getWhere(Data.class, new QueryCondition("sha512", "=", sha512)); | 			return DataAccess.getWhere(Data.class, new Condition(new QueryCondition("sha512", "=", sha512))); | ||||||
| 		} catch (final Exception e) { | 		} catch (final Exception e) { | ||||||
| 			// TODO Auto-generated catch block | 			// TODO Auto-generated catch block | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| @@ -219,6 +221,7 @@ public class DataResource { | |||||||
| 	@Path("/upload/") | 	@Path("/upload/") | ||||||
| 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | 	@Consumes({ MediaType.MULTIPART_FORM_DATA }) | ||||||
| 	@RolesAllowed("ADMIN") | 	@RolesAllowed("ADMIN") | ||||||
|  | 	@Operation(description = "Insert a new data in the data environment", tags = "SYSTEM") | ||||||
| 	public Response uploadFile(@Context final SecurityContext sc, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) { | 	public Response uploadFile(@Context final SecurityContext sc, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData) { | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| 		LOGGER.info("==================================================="); | 		LOGGER.info("==================================================="); | ||||||
| @@ -242,6 +245,7 @@ public class DataResource { | |||||||
| 	@PermitTokenInURI | 	@PermitTokenInURI | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get back some data from the data environment", tags = "SYSTEM") | ||||||
| 	public Response retriveDataId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | 	public Response retriveDataId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | ||||||
| 			@PathParam("id") final Long id) throws Exception { | 			@PathParam("id") final Long id) throws Exception { | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
| @@ -260,6 +264,7 @@ public class DataResource { | |||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	@PermitTokenInURI | 	@PermitTokenInURI | ||||||
| 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get a thumbnail of from the data environment (if resize is possible)", tags = "SYSTEM") | ||||||
| 	// @CacheMaxAge(time = 10, unit = TimeUnit.DAYS) | 	// @CacheMaxAge(time = 10, unit = TimeUnit.DAYS) | ||||||
| 	public Response retriveDataThumbnailId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | 	public Response retriveDataThumbnailId(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | ||||||
| 			@PathParam("id") final Long id) throws Exception { | 			@PathParam("id") final Long id) throws Exception { | ||||||
| @@ -319,6 +324,7 @@ public class DataResource { | |||||||
| 	@PermitTokenInURI | 	@PermitTokenInURI | ||||||
| 	@RolesAllowed("USER") | 	@RolesAllowed("USER") | ||||||
| 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | 	@Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
|  | 	@Operation(description = "Get back some data from the data environment (with a beautifull name (permit download with basic name)", tags = "SYSTEM") | ||||||
| 	public Response retriveDataFull(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | 	public Response retriveDataFull(@Context final SecurityContext sc, @QueryParam(HttpHeaders.AUTHORIZATION) final String token, @HeaderParam("Range") final String range, | ||||||
| 			@PathParam("id") final Long id, @PathParam("name") final String name) throws Exception { | 			@PathParam("id") final Long id, @PathParam("name") final String name) throws Exception { | ||||||
| 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | 		final GenericContext gc = (GenericContext) sc.getUserPrincipal(); | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import java.util.List; | |||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import jakarta.annotation.security.PermitAll; | import jakarta.annotation.security.PermitAll; | ||||||
| import jakarta.ws.rs.GET; | import jakarta.ws.rs.GET; | ||||||
| import jakarta.ws.rs.NotFoundException; | import jakarta.ws.rs.NotFoundException; | ||||||
| @@ -88,6 +89,7 @@ public class FrontGeneric { | |||||||
|  |  | ||||||
| 	@GET | 	@GET | ||||||
| 	@PermitAll() | 	@PermitAll() | ||||||
|  | 	@Operation(description = "Retrieve native element (index)", tags = "SYSTEM") | ||||||
| 	// @Produces(MediaType.APPLICATION_OCTET_STREAM) | 	// @Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
| 	// @CacheMaxAge(time = 1, unit = TimeUnit.DAYS) | 	// @CacheMaxAge(time = 1, unit = TimeUnit.DAYS) | ||||||
| 	public Response retrive0() throws Exception { | 	public Response retrive0() throws Exception { | ||||||
| @@ -97,6 +99,7 @@ public class FrontGeneric { | |||||||
| 	@GET | 	@GET | ||||||
| 	@Path("{any: .*}") | 	@Path("{any: .*}") | ||||||
| 	@PermitAll() | 	@PermitAll() | ||||||
|  | 	@Operation(description = "Get specific file from the front environment", tags = "SYSTEM") | ||||||
| 	// @Produces(MediaType.APPLICATION_OCTET_STREAM) | 	// @Produces(MediaType.APPLICATION_OCTET_STREAM) | ||||||
| 	// @CacheMaxAge(time = 10, unit = TimeUnit.DAYS) | 	// @CacheMaxAge(time = 10, unit = TimeUnit.DAYS) | ||||||
| 	public Response retrive1(@PathParam("any") final List<PathSegment> segments) throws Exception { | 	public Response retrive1(@PathParam("any") final List<PathSegment> segments) throws Exception { | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								src/org/kar/archidata/api/openApiResource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/org/kar/archidata/api/openApiResource.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | package org.kar.archidata.api; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource; | ||||||
|  | import io.swagger.v3.oas.annotations.Operation; | ||||||
|  | import jakarta.annotation.security.PermitAll; | ||||||
|  | import jakarta.servlet.ServletConfig; | ||||||
|  | import jakarta.ws.rs.GET; | ||||||
|  | import jakarta.ws.rs.Path; | ||||||
|  | import jakarta.ws.rs.Produces; | ||||||
|  | import jakarta.ws.rs.core.Application; | ||||||
|  | import jakarta.ws.rs.core.Context; | ||||||
|  | import jakarta.ws.rs.core.HttpHeaders; | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.Response; | ||||||
|  | import jakarta.ws.rs.core.UriInfo; | ||||||
|  |  | ||||||
|  | @Path("/openapi") | ||||||
|  | public class openApiResource extends BaseOpenApiResource { | ||||||
|  | 	@Context | ||||||
|  | 	ServletConfig config; | ||||||
|  |  | ||||||
|  | 	@Context | ||||||
|  | 	Application app; | ||||||
|  |  | ||||||
|  | 	@GET | ||||||
|  | 	@Path("swagger.json") | ||||||
|  | 	@Produces({ MediaType.APPLICATION_JSON }) | ||||||
|  | 	@PermitAll | ||||||
|  | 	@Operation(hidden = true, description = "Get the OPEN-API description", tags = "SYSTEM") | ||||||
|  | 	public Response getDescription(@Context final HttpHeaders headers, @Context final UriInfo uriInfo) throws Exception { | ||||||
|  | 		return getOpenApi(headers, this.config, this.app, uriInfo, "json"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -14,8 +14,8 @@ public class InputExceptionCatcher implements ExceptionMapper<InputException> { | |||||||
| 	@Override | 	@Override | ||||||
| 	public Response toResponse(final InputException exception) { | 	public Response toResponse(final InputException exception) { | ||||||
| 		final RestErrorResponse ret = build(exception); | 		final RestErrorResponse ret = build(exception); | ||||||
| 		LOGGER.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error UUID={} ==> '{}'=>'{}'", ret.uuid, exception.missingVariable, exception.getLocalizedMessage()); | ||||||
| 		exception.printStackTrace(); | 		// exception.printStackTrace(); | ||||||
| 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | 		return Response.status(exception.status).entity(ret).type(MediaType.APPLICATION_JSON).build(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								src/org/kar/archidata/catcher/JacksonCatcher.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/org/kar/archidata/catcher/JacksonCatcher.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | package org.kar.archidata.catcher; | ||||||
|  |  | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.Response; | ||||||
|  | import jakarta.ws.rs.ext.ExceptionMapper; | ||||||
|  |  | ||||||
|  | public class JacksonCatcher implements ExceptionMapper<JsonProcessingException> { | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(JacksonCatcher.class); | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public Response toResponse(final JsonProcessingException exception) { | ||||||
|  | 		LOGGER.warn("Catch exception Input data parsing:"); | ||||||
|  | 		final RestErrorResponse ret = build(exception); | ||||||
|  | 		LOGGER.error("Error UUID={}", ret.uuid); | ||||||
|  | 		exception.printStackTrace(); | ||||||
|  | 		return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ret).type(MediaType.APPLICATION_JSON).build(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private RestErrorResponse build(final Exception exception) { | ||||||
|  | 		return new RestErrorResponse(Response.Status.INTERNAL_SERVER_ERROR, "Catch JSON Exception", exception.getMessage()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -31,14 +31,22 @@ public interface DataAccessAddOn { | |||||||
| 	 * @throws SQLException */ | 	 * @throws SQLException */ | ||||||
| 	void insertData(PreparedStatement ps, final Field field, Object data, CountInOut iii) throws Exception, SQLException, IllegalArgumentException, IllegalAccessException; | 	void insertData(PreparedStatement ps, final Field field, Object data, CountInOut iii) throws Exception, SQLException, IllegalArgumentException, IllegalAccessException; | ||||||
|  |  | ||||||
| 	// Element can insert in the single request | 	/** Element can insert in the single request | ||||||
| 	boolean canInsert(final Field field); | 	 * @param field | ||||||
|  | 	 * @return */ | ||||||
|  | 	default boolean canInsert(final Field field) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Element can be retrieve with the specific mode | 	/** Element can be retrieve with the specific mode | ||||||
| 	boolean canRetrieve(final Field field); | 	 * @param field | ||||||
|  | 	 * @return */ | ||||||
|  | 	default boolean canRetrieve(final Field field) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	void generateQuerry(@NotNull String tableName, @NotNull Field field, @NotNull final StringBuilder querrySelect, @NotNull final StringBuilder querry, @NotNull String name, | 	void generateQuerry(@NotNull String tableName, @NotNull Field field, @NotNull final StringBuilder querySelect, @NotNull final StringBuilder query, @NotNull String name, @NotNull CountInOut count, | ||||||
| 			@NotNull CountInOut count, QueryOptions options) throws Exception; | 			QueryOptions options) throws Exception; | ||||||
|  |  | ||||||
| 	// Return the number of colomn read | 	// Return the number of colomn read | ||||||
| 	void fillFromQuerry(ResultSet rs, Field field, Object data, CountInOut count, QueryOptions options, final List<LazyGetter> lazyCall) | 	void fillFromQuerry(ResultSet rs, Field field, Object data, CountInOut count, QueryOptions options, final List<LazyGetter> lazyCall) | ||||||
| @@ -56,4 +64,46 @@ public interface DataAccessAddOn { | |||||||
| 	void createTables(String tableName, Field field, StringBuilder mainTableBuilder, List<String> preActionList, List<String> postActionList, boolean createIfNotExist, boolean createDrop, int fieldId) | 	void createTables(String tableName, Field field, StringBuilder mainTableBuilder, List<String> preActionList, List<String> postActionList, boolean createIfNotExist, boolean createDrop, int fieldId) | ||||||
| 			throws Exception; | 			throws Exception; | ||||||
|  |  | ||||||
|  | 	/** Some action must be done asynchronously for update or remove element | ||||||
|  | 	 * @param field | ||||||
|  | 	 * @return */ | ||||||
|  | 	default boolean isInsertAsync(final Field field) throws Exception { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** When insert is mark async, this function permit to create or update the data | ||||||
|  | 	 * @param tableName Name of the Table. | ||||||
|  | 	 * @param localId Local ID of the current table | ||||||
|  | 	 * @param field Field that is updated. | ||||||
|  | 	 * @param data Data that might be inserted. | ||||||
|  | 	 * @param actions Asynchronous action to do after main request. */ | ||||||
|  | 	default void asyncInsert(final String tableName, final Object localId, final Field field, final Object data, final List<LazyGetter> actions) throws Exception { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** Some action must be done asynchronously for update or remove element | ||||||
|  | 	 * @param field | ||||||
|  | 	 * @return */ | ||||||
|  | 	default boolean isUpdateAsync(final Field field) throws Exception { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** When insert is mark async, this function permit to create or update the data | ||||||
|  | 	 * @param tableName Name of the Table. | ||||||
|  | 	 * @param localId Local ID of the current table | ||||||
|  | 	 * @param field Field that is updated. | ||||||
|  | 	 * @param data Data that might be inserted. | ||||||
|  | 	 * @param actions Asynchronous action to do after main request. */ | ||||||
|  | 	default void asyncUpdate(final String tableName, final Object localId, final Field field, final Object data, final List<LazyGetter> actions) throws Exception { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	default void drop(final String tableName, final Field field) throws Exception { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	default void cleanAll(final String tableName, final Field field) throws Exception { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -131,8 +131,8 @@ public class DataFactory { | |||||||
| 	public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> preOtherTables, final List<String> postOtherTables, | 	public static void createTablesSpecificType(final String tableName, final Field elem, final StringBuilder mainTableBuilder, final List<String> preOtherTables, final List<String> postOtherTables, | ||||||
| 			final boolean createIfNotExist, final boolean createDrop, final int fieldId, final Class<?> classModel) throws Exception { | 			final boolean createIfNotExist, final boolean createDrop, final int fieldId, final Class<?> classModel) throws Exception { | ||||||
| 		final String name = AnnotationTools.getFieldName(elem); | 		final String name = AnnotationTools.getFieldName(elem); | ||||||
| 		final Integer limitSize = AnnotationTools.getLimitSize(elem); | 		final int limitSize = AnnotationTools.getLimitSize(elem); | ||||||
| 		final boolean notNull = AnnotationTools.getNotNull(elem); | 		final boolean notNull = AnnotationTools.getColumnNotNull(elem); | ||||||
|  |  | ||||||
| 		final boolean primaryKey = AnnotationTools.isPrimaryKey(elem); | 		final boolean primaryKey = AnnotationTools.isPrimaryKey(elem); | ||||||
| 		final GenerationType strategy = AnnotationTools.getStrategy(elem); | 		final GenerationType strategy = AnnotationTools.getStrategy(elem); | ||||||
| @@ -152,7 +152,7 @@ public class DataFactory { | |||||||
| 		String typeValue = null; | 		String typeValue = null; | ||||||
| 		typeValue = convertTypeInSQL(classModel, name); | 		typeValue = convertTypeInSQL(classModel, name); | ||||||
| 		if ("text".equals(typeValue) && !"sqlite".equals(ConfigBaseVariable.getDBType())) { | 		if ("text".equals(typeValue) && !"sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			if (limitSize != null) { | 			if (limitSize > 0) { | ||||||
| 				mainTableBuilder.append("varchar("); | 				mainTableBuilder.append("varchar("); | ||||||
| 				mainTableBuilder.append(limitSize); | 				mainTableBuilder.append(limitSize); | ||||||
| 				mainTableBuilder.append(")"); | 				mainTableBuilder.append(")"); | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								src/org/kar/archidata/dataAccess/Limit.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/org/kar/archidata/dataAccess/Limit.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | package org.kar.archidata.dataAccess; | ||||||
|  |  | ||||||
|  | import java.sql.PreparedStatement; | ||||||
|  |  | ||||||
|  | public class Limit extends QueryOption { | ||||||
|  | 	protected final long limit; | ||||||
|  |  | ||||||
|  | 	public Limit(final long limit) { | ||||||
|  | 		this.limit = limit; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
|  | 		query.append(" LIMIT ? "); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void injectQuerry(final PreparedStatement ps, final CountInOut iii) throws Exception { | ||||||
|  | 		DataAccess.addElement(ps, this.limit, iii); | ||||||
|  | 		iii.inc(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/org/kar/archidata/dataAccess/OrderBy.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/org/kar/archidata/dataAccess/OrderBy.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | package org.kar.archidata.dataAccess; | ||||||
|  |  | ||||||
|  | import java.sql.PreparedStatement; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | public class OrderBy extends QueryOption { | ||||||
|  | 	protected final List<OrderItem> childs; | ||||||
|  |  | ||||||
|  | 	public OrderBy(final List<OrderItem> childs) { | ||||||
|  | 		this.childs = childs; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public OrderBy(final OrderItem... childs) { | ||||||
|  | 		this.childs = List.of(childs); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
|  | 		if (this.childs.size() >= 1) { | ||||||
|  | 			query.append(" ORDER BY "); | ||||||
|  | 		} | ||||||
|  | 		boolean first = true; | ||||||
|  | 		for (final OrderItem elem : this.childs) { | ||||||
|  | 			if (first) { | ||||||
|  | 				first = false; | ||||||
|  | 			} else { | ||||||
|  | 				query.append(", "); | ||||||
|  | 			} | ||||||
|  | 			query.append("`"); | ||||||
|  | 			query.append(elem.value); | ||||||
|  | 			query.append("` "); | ||||||
|  | 			query.append(elem.order.toString()); | ||||||
|  | 		} | ||||||
|  | 		if (this.childs.size() >= 1) { | ||||||
|  | 			query.append(")"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void injectQuerry(final PreparedStatement ps, final CountInOut iii) throws Exception { | ||||||
|  | 		// nothing to add. | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								src/org/kar/archidata/dataAccess/OrderItem.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/org/kar/archidata/dataAccess/OrderItem.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | package org.kar.archidata.dataAccess; | ||||||
|  |  | ||||||
|  | public class OrderItem { | ||||||
|  | 	public enum Order { | ||||||
|  | 		ASC, DESC | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	public final String value; | ||||||
|  | 	public final Order order; | ||||||
|  |  | ||||||
|  | 	public OrderItem(final String value, final Order order) { | ||||||
|  | 		this.value = value; | ||||||
|  | 		this.order = order; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -18,21 +18,21 @@ public class QueryAnd implements QueryItem { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void generateQuerry(final StringBuilder querry, final String tableName) { | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
| 		if (this.childs.size() >= 1) { | 		if (this.childs.size() >= 1) { | ||||||
| 			querry.append(" ("); | 			query.append(" ("); | ||||||
| 		} | 		} | ||||||
| 		boolean first = true; | 		boolean first = true; | ||||||
| 		for (final QueryItem elem : this.childs) { | 		for (final QueryItem elem : this.childs) { | ||||||
| 			if (first) { | 			if (first) { | ||||||
| 				first = false; | 				first = false; | ||||||
| 			} else { | 			} else { | ||||||
| 				querry.append(" AND "); | 				query.append(" AND "); | ||||||
| 			} | 			} | ||||||
| 			elem.generateQuerry(querry, tableName); | 			elem.generateQuerry(query, tableName); | ||||||
| 		} | 		} | ||||||
| 		if (this.childs.size() >= 1) { | 		if (this.childs.size() >= 1) { | ||||||
| 			querry.append(")"); | 			query.append(")"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,14 +14,13 @@ public class QueryCondition implements QueryItem { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void generateQuerry(final StringBuilder querry, final String tableName) { | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
| 		querry.append(tableName); | 		query.append(tableName); | ||||||
| 		querry.append("."); | 		query.append("."); | ||||||
| 		querry.append(this.key); | 		query.append(this.key); | ||||||
| 		querry.append(" "); | 		query.append(" "); | ||||||
| 		querry.append(this.comparator); | 		query.append(this.comparator); | ||||||
| 		querry.append(" ?"); | 		query.append(" ?"); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
|   | |||||||
| @@ -18,22 +18,26 @@ public class QueryInList<T> implements QueryItem { | |||||||
| 		this(key, "IN", value); | 		this(key, "IN", value); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public QueryInList(final String key, final T... value) { | ||||||
|  | 		this(key, "IN", List.of(value)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void generateQuerry(final StringBuilder querry, final String tableName) { | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
| 		querry.append(tableName); | 		query.append(tableName); | ||||||
| 		querry.append("."); | 		query.append("."); | ||||||
| 		querry.append(this.key); | 		query.append(this.key); | ||||||
| 		querry.append(" "); | 		query.append(" "); | ||||||
| 		querry.append(this.comparator); | 		query.append(this.comparator); | ||||||
| 		querry.append(" ("); | 		query.append(" ("); | ||||||
| 		for (int iii = 0; iii < this.value.size(); iii++) { | 		for (int iii = 0; iii < this.value.size(); iii++) { | ||||||
| 			if (iii != 0) { | 			if (iii != 0) { | ||||||
| 				querry.append(",?"); | 				query.append(",?"); | ||||||
| 			} else { | 			} else { | ||||||
| 				querry.append("?"); | 				query.append("?"); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		querry.append(")"); | 		query.append(")"); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package org.kar.archidata.dataAccess; | |||||||
| import java.sql.PreparedStatement; | import java.sql.PreparedStatement; | ||||||
|  |  | ||||||
| public interface QueryItem { | public interface QueryItem { | ||||||
| 	void generateQuerry(StringBuilder querry, String tableName); | 	void generateQuerry(StringBuilder query, String tableName); | ||||||
|  |  | ||||||
| 	void injectQuerry(PreparedStatement ps, CountInOut iii) throws Exception; | 	void injectQuerry(PreparedStatement ps, CountInOut iii) throws Exception; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,12 +18,15 @@ public class QueryOptions { | |||||||
| 	 | 	 | ||||||
| 	private final List<QueryOption> options = new ArrayList<>(); | 	private final List<QueryOption> options = new ArrayList<>(); | ||||||
| 	 | 	 | ||||||
|  | 	public QueryOptions() {} | ||||||
|  | 	 | ||||||
| 	public QueryOptions(final QueryOption... elems) { | 	public QueryOptions(final QueryOption... elems) { | ||||||
|  | 		if (elems == null || elems.length == 0) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
| 		Collections.addAll(this.options, elems); | 		Collections.addAll(this.options, elems); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	public QueryOptions() {} |  | ||||||
|  |  | ||||||
| 	public void add(final QueryOption option) { | 	public void add(final QueryOption option) { | ||||||
| 		this.options.add(option); | 		this.options.add(option); | ||||||
| 	} | 	} | ||||||
| @@ -32,6 +35,10 @@ public class QueryOptions { | |||||||
| 		return this.options; | 		return this.options; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	public QueryOption[] getAllArray() { | ||||||
|  | 		return this.options.toArray(new QueryOption[0]); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	@SuppressWarnings("unchecked") | 	@SuppressWarnings("unchecked") | ||||||
| 	public <T> T get(final Class<T> type) { | 	public <T> T get(final Class<T> type) { | ||||||
| 		for (final QueryOption elem : this.options) { | 		for (final QueryOption elem : this.options) { | ||||||
| @@ -57,5 +64,4 @@ public class QueryOptions { | |||||||
| 		} | 		} | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,22 +10,26 @@ public class QueryOr implements QueryItem { | |||||||
| 		this.childs = childs; | 		this.childs = childs; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public QueryOr(final QueryItem... childs) { | ||||||
|  | 		this.childs = List.of(childs); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void generateQuerry(final StringBuilder querry, final String tableName) { | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
| 		if (this.childs.size() >= 1) { | 		if (this.childs.size() >= 1) { | ||||||
| 			querry.append(" ("); | 			query.append(" ("); | ||||||
| 		} | 		} | ||||||
| 		boolean first = true; | 		boolean first = true; | ||||||
| 		for (final QueryItem elem : this.childs) { | 		for (final QueryItem elem : this.childs) { | ||||||
| 			if (first) { | 			if (first) { | ||||||
| 				first = false; | 				first = false; | ||||||
| 			} else { | 			} else { | ||||||
| 				querry.append(" OR "); | 				query.append(" OR "); | ||||||
| 			} | 			} | ||||||
| 			elem.generateQuerry(querry, tableName); | 			elem.generateQuerry(query, tableName); | ||||||
| 		} | 		} | ||||||
| 		if (this.childs.size() >= 1) { | 		if (this.childs.size() >= 1) { | ||||||
| 			querry.append(")"); | 			query.append(")"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								src/org/kar/archidata/dataAccess/RetreiveFromDB.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/org/kar/archidata/dataAccess/RetreiveFromDB.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | package org.kar.archidata.dataAccess; | ||||||
|  |  | ||||||
|  | import java.sql.ResultSet; | ||||||
|  |  | ||||||
|  | public interface RetreiveFromDB { | ||||||
|  | 	void doRequest(final ResultSet rs, Object obj) throws Exception; | ||||||
|  | } | ||||||
| @@ -58,6 +58,11 @@ public class AddOnDataJson implements DataAccessAddOn { | |||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isInsertAsync(final Field field) throws Exception { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean canRetrieve(final Field field) { | 	public boolean canRetrieve(final Field field) { | ||||||
| 		return true; | 		return true; | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import org.kar.archidata.dataAccess.QueryCondition; | |||||||
| import org.kar.archidata.dataAccess.QueryInList; | import org.kar.archidata.dataAccess.QueryInList; | ||||||
| import org.kar.archidata.dataAccess.QueryOptions; | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
| import org.kar.archidata.dataAccess.addOn.model.LinkTable; | import org.kar.archidata.dataAccess.addOn.model.LinkTable; | ||||||
|  | import org.kar.archidata.dataAccess.options.Condition; | ||||||
| import org.kar.archidata.dataAccess.options.OverrideTableName; | import org.kar.archidata.dataAccess.options.OverrideTableName; | ||||||
| import org.kar.archidata.exception.DataAccessException; | import org.kar.archidata.exception.DataAccessException; | ||||||
| import org.kar.archidata.tools.ConfigBaseVariable; | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
| @@ -85,7 +86,7 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		querrySelect.append(" (SELECT GROUP_CONCAT("); | 		querrySelect.append(" (SELECT GROUP_CONCAT("); | ||||||
| 		querrySelect.append(tmpVariable); | 		querrySelect.append(tmpVariable); | ||||||
| 		querrySelect.append(".object2Id "); | 		querrySelect.append(".object2Id "); | ||||||
| 		if (ConfigBaseVariable.getDBType().equals("sqlite")) { | 		if ("sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			querrySelect.append(", "); | 			querrySelect.append(", "); | ||||||
| 		} else { | 		} else { | ||||||
| 			querrySelect.append("SEPARATOR "); | 			querrySelect.append("SEPARATOR "); | ||||||
| @@ -97,14 +98,13 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		querrySelect.append(" "); | 		querrySelect.append(" "); | ||||||
| 		querrySelect.append(tmpVariable); | 		querrySelect.append(tmpVariable); | ||||||
| 		querrySelect.append(" WHERE "); | 		querrySelect.append(" WHERE "); | ||||||
| 		querrySelect.append(tmpVariable); | 		/* querrySelect.append(tmpVariable); querrySelect.append(".deleted = false AND "); */ | ||||||
| 		querrySelect.append(".deleted = false AND "); |  | ||||||
| 		querrySelect.append(tableName); | 		querrySelect.append(tableName); | ||||||
| 		querrySelect.append(".id = "); | 		querrySelect.append(".id = "); | ||||||
| 		querrySelect.append(tmpVariable); | 		querrySelect.append(tmpVariable); | ||||||
| 		querrySelect.append("."); | 		querrySelect.append("."); | ||||||
| 		querrySelect.append("object1Id "); | 		querrySelect.append("object1Id "); | ||||||
| 		if (!ConfigBaseVariable.getDBType().equals("sqlite")) { | 		if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { | ||||||
| 			querrySelect.append(" GROUP BY "); | 			querrySelect.append(" GROUP BY "); | ||||||
| 			querrySelect.append(tmpVariable); | 			querrySelect.append(tmpVariable); | ||||||
| 			querrySelect.append(".object1Id"); | 			querrySelect.append(".object1Id"); | ||||||
| @@ -143,6 +143,7 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 	@Override | 	@Override | ||||||
| 	public void fillFromQuerry(final ResultSet rs, final Field field, final Object data, final CountInOut count, final QueryOptions options, final List<LazyGetter> lazyCall) throws Exception { | 	public void fillFromQuerry(final ResultSet rs, final Field field, final Object data, final CountInOut count, final QueryOptions options, final List<LazyGetter> lazyCall) throws Exception { | ||||||
| 		if (field.getType() != List.class) { | 		if (field.getType() != List.class) { | ||||||
|  | 			LOGGER.error("Can not ManyToMany with other than List Model: {}", field.getType().getCanonicalName()); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; | 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; | ||||||
| @@ -150,6 +151,10 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 			final List<Long> idList = DataAccess.getListOfIds(rs, count.value, SEPARATOR); | 			final List<Long> idList = DataAccess.getListOfIds(rs, count.value, SEPARATOR); | ||||||
| 			field.set(data, idList); | 			field.set(data, idList); | ||||||
| 			count.inc(); | 			count.inc(); | ||||||
|  | 			return; | ||||||
|  | 			// } else { | ||||||
|  | 			// LOGGER.error("Can not ManyToMany with other than List<Long> Model: List<{}>", objectClass.getCanonicalName()); | ||||||
|  | 			// return; | ||||||
| 		} | 		} | ||||||
| 		final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); | 		final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class); | ||||||
| 		if (decorators == null) { | 		if (decorators == null) { | ||||||
| @@ -169,7 +174,7 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 						final List<Long> childs = new ArrayList<>(idList); | 						final List<Long> childs = new ArrayList<>(idList); | ||||||
| 						// TODO: update to have get with abstract types .... | 						// TODO: update to have get with abstract types .... | ||||||
| 						@SuppressWarnings("unchecked") | 						@SuppressWarnings("unchecked") | ||||||
| 						final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(), new QueryInList<>(idField, childs), null); | 						final Object foreignData = DataAccess.getsWhere(decorators.targetEntity(), new Condition(new QueryInList<>(idField, childs))); | ||||||
| 						if (foreignData == null) { | 						if (foreignData == null) { | ||||||
| 							return; | 							return; | ||||||
| 						} | 						} | ||||||
| @@ -181,21 +186,98 @@ public class AddOnManyToMany implements DataAccessAddOn { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isUpdateAsync(final Field field) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void asyncUpdate(final String tableName, final Object localKey, final Field field, final Object data, final List<LazyGetter> actions) throws Exception { | ||||||
|  | 		if (field.getType() != List.class) { | ||||||
|  | 			LOGGER.error("Can not ManyToMany with other than List Model: {}", field.getType().getCanonicalName()); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		final String columnName = AnnotationTools.getFieldName(field); | ||||||
|  | 		final String linkTableName = generateLinkTableName(tableName, columnName); | ||||||
|  | 		actions.add(() -> { | ||||||
|  | 			DataAccess.deleteWhere(LinkTable.class, new OverrideTableName(linkTableName), new Condition(new QueryCondition("object1Id", "=", localKey))); | ||||||
|  | 		}); | ||||||
|  | 		asyncInsert(tableName, localKey, field, data, actions); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isInsertAsync(final Field field) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void asyncInsert(final String tableName, final Object localKey, final Field field, final Object data, final List<LazyGetter> actions) throws Exception { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		if (field.getType() != List.class) { | ||||||
|  | 			LOGGER.error("Can not ManyToMany with other than List Model: {}", field.getType().getCanonicalName()); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		final String columnName = AnnotationTools.getFieldName(field); | ||||||
|  | 		final String linkTableName = generateLinkTableName(tableName, columnName); | ||||||
|  | 		final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; | ||||||
|  | 		if (objectClass != Long.class) { | ||||||
|  | 			LOGGER.error("Can not ManyToMany with other than List<Long> Model: List<{}>", objectClass.getCanonicalName()); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		@SuppressWarnings("unchecked") | ||||||
|  | 		final List<Long> dataCasted = (List<Long>) data; | ||||||
|  | 		if (dataCasted.size() == 0) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		final List<LinkTable> insertElements = new ArrayList<>(); | ||||||
|  | 		for (final Long remoteKey : dataCasted) { | ||||||
|  | 			if (remoteKey == null) { | ||||||
|  | 				throw new DataAccessException("Try to insert remote key with null value"); | ||||||
|  | 			} | ||||||
|  | 			if (localKey instanceof final Long localKeyLong) { | ||||||
|  | 				insertElements.add(new LinkTable(localKeyLong, remoteKey)); | ||||||
|  | 			} else { | ||||||
|  | 				throw new DataAccessException("Not manage access of remte key like ManyToMany other than Long: " + localKey.getClass().getCanonicalName()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (insertElements.size() == 0) { | ||||||
|  | 			LOGGER.warn("Insert multiple link without any value (may have null in the list): {}", dataCasted); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		actions.add(() -> { | ||||||
|  | 			DataAccess.insertMultiple(insertElements, new OverrideTableName(linkTableName)); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void drop(final String tableName, final Field field) throws Exception { | ||||||
|  | 		final String columnName = AnnotationTools.getFieldName(field); | ||||||
|  | 		final String linkTableName = generateLinkTableName(tableName, columnName); | ||||||
|  | 		DataAccess.drop(LinkTable.class, new OverrideTableName(linkTableName)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void cleanAll(final String tableName, final Field field) throws Exception { | ||||||
|  | 		final String columnName = AnnotationTools.getFieldName(field); | ||||||
|  | 		final String linkTableName = generateLinkTableName(tableName, columnName); | ||||||
|  | 		DataAccess.cleanAll(LinkTable.class, new OverrideTableName(linkTableName)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	public static void addLink(final Class<?> clazz, final long localKey, final String column, final long remoteKey) throws Exception { | 	public static void addLink(final Class<?> clazz, final long localKey, final String column, final long remoteKey) throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final String linkTableName = generateLinkTableName(tableName, column); | 		final String linkTableName = generateLinkTableName(tableName, column); | ||||||
| 		final LinkTable insertElement = new LinkTable(localKey, remoteKey); | 		final LinkTable insertElement = new LinkTable(localKey, remoteKey); | ||||||
| 		final QueryOptions options = new QueryOptions(new OverrideTableName(linkTableName)); | 		DataAccess.insert(insertElement, new OverrideTableName(linkTableName)); | ||||||
| 		DataAccess.insert(insertElement, options); |  | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static int removeLink(final Class<?> clazz, final long localKey, final String column, final long remoteKey) throws Exception { | 	public static int removeLink(final Class<?> clazz, final long localKey, final String column, final long remoteKey) throws Exception { | ||||||
| 		final String tableName = AnnotationTools.getTableName(clazz); | 		final String tableName = AnnotationTools.getTableName(clazz); | ||||||
| 		final String linkTableName = generateLinkTableName(tableName, column); | 		final String linkTableName = generateLinkTableName(tableName, column); | ||||||
| 		final QueryOptions options = new QueryOptions(new OverrideTableName(linkTableName)); | 		return DataAccess.deleteWhere(LinkTable.class, new OverrideTableName(linkTableName), | ||||||
| 		final QueryAnd condition = new QueryAnd(new QueryCondition("object1Id", "=", localKey), new QueryCondition("object2Id", "=", remoteKey)); | 				new Condition(new QueryAnd(new QueryCondition("object1Id", "=", localKey), new QueryCondition("object2Id", "=", remoteKey)))); | ||||||
| 		return DataAccess.deleteWhere(LinkTable.class, condition, options); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
|   | |||||||
| @@ -81,6 +81,11 @@ public class AddOnManyToOne implements DataAccessAddOn { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isInsertAsync(final Field field) throws Exception { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean canRetrieve(final Field field) { | 	public boolean canRetrieve(final Field field) { | ||||||
| 		if (field.getType() == Long.class) { | 		if (field.getType() == Long.class) { | ||||||
|   | |||||||
| @@ -92,6 +92,11 @@ public class AddOnOneToMany implements DataAccessAddOn { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isInsertAsync(final Field field) throws Exception { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean canRetrieve(final Field field) { | 	public boolean canRetrieve(final Field field) { | ||||||
| 		return false; | 		return false; | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory; | |||||||
|  |  | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
|  |  | ||||||
|  | // TODO: maybe deprecated ==> use DataJson instead... | ||||||
| public class AddOnSQLTableExternalForeinKeyAsList implements DataAccessAddOn { | public class AddOnSQLTableExternalForeinKeyAsList implements DataAccessAddOn { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class); | ||||||
| 	static final String SEPARATOR = "-"; | 	static final String SEPARATOR = "-"; | ||||||
| @@ -76,10 +77,15 @@ public class AddOnSQLTableExternalForeinKeyAsList implements DataAccessAddOn { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean canRetrieve(final Field field) { | 	public boolean isInsertAsync(final Field field) throws Exception { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean canRetrieve(final Field field) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public void generateQuerry(@NotNull final String tableName, @NotNull final Field field, @NotNull final StringBuilder querrySelect, @NotNull final StringBuilder querry, @NotNull final String name, | 	public void generateQuerry(@NotNull final String tableName, @NotNull final Field field, @NotNull final StringBuilder querrySelect, @NotNull final StringBuilder querry, @NotNull final String name, | ||||||
| 			@NotNull final CountInOut elemCount, final QueryOptions options) { | 			@NotNull final CountInOut elemCount, final QueryOptions options) { | ||||||
|   | |||||||
| @@ -1,11 +1,11 @@ | |||||||
| package org.kar.archidata.dataAccess.addOn.model; | package org.kar.archidata.dataAccess.addOn.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataComment; | import org.kar.archidata.model.GenericData; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; |  | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
|  |  | ||||||
| public class LinkTable extends GenericDataSoftDelete { | public class LinkTable extends GenericData { | ||||||
| 	public LinkTable() { | 	public LinkTable() { | ||||||
| 		// nothing to do... | 		// nothing to do... | ||||||
| 	} | 	} | ||||||
| @@ -15,10 +15,10 @@ public class LinkTable extends GenericDataSoftDelete { | |||||||
| 		this.object2Id = object2Id; | 		this.object2Id = object2Id; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@DataComment("Object reference 1") | 	@Schema(description = "Object reference 1") | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	public Long object1Id; | 	public Long object1Id; | ||||||
| 	@DataComment("Object reference 2") | 	@Schema(description = "Object reference 2") | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	public Long object2Id; | 	public Long object2Id; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,12 +2,19 @@ package org.kar.archidata.dataAccess.options; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.AnnotationTools; | ||||||
|  |  | ||||||
| /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
| public interface CheckFunctionInterface { | public interface CheckFunctionInterface { | ||||||
| 	/** This function implementation is design to check if the updated class is valid of not for insertion | 	/** This function implementation is design to check if the updated class is valid of not for insertion | ||||||
|  | 	 * @param baseName NAme of the object to be precise with the use of what fail. | ||||||
| 	 * @param data The object that might be injected. | 	 * @param data The object that might be injected. | ||||||
| 	 * @param filterValue List of fields that might be check. If null, then all column must be checked. | 	 * @param filterValue List of fields that might be check. If null, then all column must be checked. | ||||||
| 	 * @throws Exception Exception is generate if the data are incorrect. */ | 	 * @throws Exception Exception is generate if the data are incorrect. */ | ||||||
| 	void check(Object data, List<String> filterValue) throws Exception; | 	void check(final String baseName, Object data, List<String> filterValue) throws Exception; | ||||||
|  |  | ||||||
|  | 	default void checkAll(final String baseName, final Object data) throws Exception { | ||||||
|  | 		check(baseName, data, AnnotationTools.getAllFieldsNames(data.getClass())); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
|  | public class CheckFunctionVoid implements CheckFunctionInterface { | ||||||
|  | 	@Override | ||||||
|  | 	public void check(final String baseName, Object data, List<String> filterValue) { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										335
									
								
								src/org/kar/archidata/dataAccess/options/CheckJPA.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								src/org/kar/archidata/dataAccess/options/CheckJPA.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,335 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import java.lang.reflect.Field; | ||||||
|  | import java.sql.Timestamp; | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalTime; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.AnnotationTools; | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.dataAccess.DataAccess; | ||||||
|  | import org.kar.archidata.dataAccess.QueryCondition; | ||||||
|  | import org.kar.archidata.exception.DataAccessException; | ||||||
|  | import org.kar.archidata.exception.InputException; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonValue; | ||||||
|  |  | ||||||
|  | import jakarta.persistence.ManyToOne; | ||||||
|  | import jakarta.validation.constraints.Size; | ||||||
|  |  | ||||||
|  | public class CheckJPA<T> implements CheckFunctionInterface { | ||||||
|  |  | ||||||
|  | 	private static final Logger LOGGER = LoggerFactory.getLogger(CheckJPA.class); | ||||||
|  | 	private final Class<?> clazz; | ||||||
|  |  | ||||||
|  | 	/** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
|  | 	public interface CheckInterface<K> { | ||||||
|  | 		/** This function implementation is design to check if the updated class is valid of not for insertion | ||||||
|  | 		 * @param data The object that might be injected. | ||||||
|  | 		 * @param filterValue List of fields that might be check. If null, then all column must be checked. | ||||||
|  | 		 * @throws Exception Exception is generate if the data are incorrect. */ | ||||||
|  | 		void check(final String baseName, final K data) throws Exception; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	protected Map<String, List<CheckInterface<T>>> checking = null; | ||||||
|  |  | ||||||
|  | 	protected void add(final String field, final CheckInterface<T> checkFunction) { | ||||||
|  | 		List<CheckInterface<T>> actions = this.checking.get(field); | ||||||
|  | 		if (actions == null) { | ||||||
|  | 			actions = new ArrayList<>(); | ||||||
|  | 			this.checking.put(field, actions); | ||||||
|  | 		} | ||||||
|  | 		actions.add(checkFunction); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public CheckJPA(final Class<T> clazz) { | ||||||
|  | 		this.clazz = clazz; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void initialize() throws Exception { | ||||||
|  | 		if (this.checking != null) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		try { | ||||||
|  | 			this.checking = new HashMap<>(); | ||||||
|  | 			// create Table: | ||||||
|  | 			final List<String> primaryKeys = new ArrayList<>(); | ||||||
|  | 			for (final Field field : this.clazz.getFields()) { | ||||||
|  | 				final String fieldName = field.getName(); // AnnotationTools.getFieldName(field); | ||||||
|  | 				if (AnnotationTools.isPrimaryKey(field)) { | ||||||
|  | 					add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 						throw new InputException(baseName + fieldName, "This is a '@Id' (primaryKey) ==> can not be change"); | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 				if (AnnotationTools.getConstraintsNotNull(field)) { | ||||||
|  | 					add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 						if (field.get(data) == null) { | ||||||
|  | 							throw new InputException(baseName + fieldName, "Can not be null"); | ||||||
|  | 						} | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 				if (AnnotationTools.isCreatedAtField(field) || AnnotationTools.isUpdateAtField(field)) { | ||||||
|  | 					add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 						throw new InputException(baseName + fieldName, "It is forbidden to change this field"); | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				final Class<?> type = field.getType(); | ||||||
|  | 				if (type == Long.class || type == long.class) { | ||||||
|  | 					final Long maxValue = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValue != null) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Long elemTyped = (Long) elem; | ||||||
|  | 							if (elemTyped > maxValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final Long minValue = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValue != null) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Long elemTyped = (Long) elem; | ||||||
|  | 							if (elemTyped < minValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | ||||||
|  | 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem); | ||||||
|  | 							if (count == 0) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Foreign element does not exist in the DB:" + elem); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 				} else if (type == Integer.class || type == int.class) { | ||||||
|  |  | ||||||
|  | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final int maxValue = maxValueRoot.intValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Integer elemTyped = (Integer) elem; | ||||||
|  | 							if (elemTyped > maxValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final int minValue = minValueRoot.intValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Integer elemTyped = (Integer) elem; | ||||||
|  | 							if (elemTyped < minValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final ManyToOne annotationManyToOne = AnnotationTools.getManyToOne(field); | ||||||
|  | 					if (annotationManyToOne != null && annotationManyToOne.targetEntity() != null) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final long count = DataAccess.count(annotationManyToOne.targetEntity(), elem); | ||||||
|  | 							if (count == 0) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Foreign element does not exist in the DB:" + elem); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Boolean.class || type == boolean.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == Float.class || type == float.class) { | ||||||
|  | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final float maxValue = maxValueRoot.floatValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Float elemTyped = (Float) elem; | ||||||
|  | 							if (elemTyped > maxValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final float minValue = minValueRoot.floatValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Float elemTyped = (Float) elem; | ||||||
|  | 							if (elemTyped < minValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Double.class || type == double.class) { | ||||||
|  | 					final Long maxValueRoot = AnnotationTools.getConstraintsMax(field); | ||||||
|  | 					if (maxValueRoot != null) { | ||||||
|  | 						final double maxValue = maxValueRoot.doubleValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Double elemTyped = (Double) elem; | ||||||
|  | 							if (elemTyped > maxValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too height max: " + maxValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final Long minValueRoot = AnnotationTools.getConstraintsMin(field); | ||||||
|  | 					if (minValueRoot != null) { | ||||||
|  | 						final double minValue = minValueRoot.doubleValue(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final Double elemTyped = (Double) elem; | ||||||
|  | 							if (elemTyped < minValue) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Value too Low min: " + minValue); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == Date.class || type == Timestamp.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == LocalDate.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == LocalTime.class) { | ||||||
|  |  | ||||||
|  | 				} else if (type == String.class) { | ||||||
|  | 					final int maxSizeString = AnnotationTools.getLimitSize(field); | ||||||
|  | 					if (maxSizeString > 0) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final String elemTyped = (String) elem; | ||||||
|  | 							if (elemTyped.length() > maxSizeString) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Too long size must be <= " + maxSizeString); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final Size limitSize = AnnotationTools.getConstraintsSize(field); | ||||||
|  | 					if (limitSize != null) { | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final String elemTyped = (String) elem; | ||||||
|  | 							if (elemTyped.length() > limitSize.max()) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Too long size (constraints) must be <= " + limitSize.max()); | ||||||
|  | 							} | ||||||
|  | 							if (elemTyped.length() < limitSize.min()) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "Too small size (constraints) must be >= " + limitSize.max()); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 					final String patternString = AnnotationTools.getConstraintsPattern(field); | ||||||
|  | 					if (patternString != null) { | ||||||
|  | 						final Pattern pattern = Pattern.compile(patternString); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							final Object elem = field.get(data); | ||||||
|  | 							if (elem == null) { | ||||||
|  | 								return; | ||||||
|  | 							} | ||||||
|  | 							final String elemTyped = (String) elem; | ||||||
|  | 							if (!pattern.matcher(elemTyped).find()) { | ||||||
|  | 								throw new InputException(baseName + fieldName, "does not match the required pattern (constraints) must be '" + patternString + "'"); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type == JsonValue.class) { | ||||||
|  | 					final DataJson jsonAnnotation = AnnotationTools.getDataJson(field); | ||||||
|  | 					if (jsonAnnotation != null && jsonAnnotation.checker() != CheckFunctionVoid.class) { | ||||||
|  | 						// Here if we have an error it crash at start and no new instance after creation... | ||||||
|  | 						final CheckFunctionInterface instance = jsonAnnotation.checker().getDeclaredConstructor().newInstance(); | ||||||
|  | 						add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 							instance.checkAll(baseName + fieldName + ".", field.get(data)); | ||||||
|  | 						}); | ||||||
|  | 					} | ||||||
|  | 				} else if (type.isEnum()) { | ||||||
|  | 					// nothing to do. | ||||||
|  | 				} | ||||||
|  | 				// keep this is last ==> take more time... | ||||||
|  | 				if (AnnotationTools.isUnique(field)) { | ||||||
|  | 					// Create the request ... | ||||||
|  | 					add(fieldName, (final String baseName, final T data) -> { | ||||||
|  | 						final Object other = DataAccess.getWhere(this.clazz, new Condition(new QueryCondition(fieldName, "==", field.get(data)))); | ||||||
|  | 						if (other != null) { | ||||||
|  | 							throw new InputException(baseName + fieldName, "Name already exist in the DB"); | ||||||
|  | 						} | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  | 		} catch (final Exception ex) { | ||||||
|  | 			this.checking = null; | ||||||
|  | 			throw ex; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void check(final String baseName, final Object data, final List<String> filterValue) throws Exception { | ||||||
|  | 		if (this.checking == null) { | ||||||
|  | 			initialize(); | ||||||
|  | 		} | ||||||
|  | 		if (!(this.clazz.isAssignableFrom(data.getClass()))) { | ||||||
|  | 			throw new DataAccessException("Incompatatyble type of Object" + data.getClass().getCanonicalName()); | ||||||
|  | 		} | ||||||
|  | 		@SuppressWarnings("unchecked") | ||||||
|  | 		final T dataCasted = (T) data; | ||||||
|  | 		for (final String filter : filterValue) { | ||||||
|  | 			final List<CheckInterface<T>> actions = this.checking.get(filter); | ||||||
|  | 			if (actions == null) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			for (final CheckInterface<T> action : actions) { | ||||||
|  | 				action.check(baseName, dataCasted); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		checkTyped(dataCasted, filterValue); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void checkTyped(final T data, final List<String> filterValue) throws Exception { | ||||||
|  | 		// nothing to do ... | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										62
									
								
								src/org/kar/archidata/dataAccess/options/Condition.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/org/kar/archidata/dataAccess/options/Condition.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import java.sql.PreparedStatement; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.CountInOut; | ||||||
|  | import org.kar.archidata.dataAccess.QueryItem; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
|  |  | ||||||
|  | /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
|  | public class Condition extends QueryOption { | ||||||
|  | 	public final QueryItem condition; | ||||||
|  |  | ||||||
|  | 	public Condition(final QueryItem items) { | ||||||
|  | 		this.condition = items; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Condition() { | ||||||
|  | 		this.condition = null; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void generateQuerry(final StringBuilder query, final String tableName) { | ||||||
|  | 		if (this.condition != null) { | ||||||
|  | 			this.condition.generateQuerry(query, tableName); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void injectQuerry(final PreparedStatement ps, final CountInOut iii) throws Exception { | ||||||
|  | 		if (this.condition != null) { | ||||||
|  | 			this.condition.injectQuerry(ps, iii); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public void whereAppendQuery(final StringBuilder query, final String tableName, final QueryOptions options, final String deletedFieldName) { | ||||||
|  | 		boolean exclude_deleted = true; | ||||||
|  | 		if (options != null) { | ||||||
|  | 			exclude_deleted = !options.exist(AccessDeletedItems.class); | ||||||
|  | 		} | ||||||
|  | 		// Check if we have a condition to generate | ||||||
|  | 		if (this.condition == null) { | ||||||
|  | 			if (exclude_deleted && deletedFieldName != null) { | ||||||
|  | 				query.append(" WHERE "); | ||||||
|  | 				query.append(tableName); | ||||||
|  | 				query.append("."); | ||||||
|  | 				query.append(deletedFieldName); | ||||||
|  | 				query.append(" = false "); | ||||||
|  | 			} | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		query.append(" WHERE ("); | ||||||
|  | 		this.condition.generateQuerry(query, tableName); | ||||||
|  |  | ||||||
|  | 		query.append(") "); | ||||||
|  | 		if (exclude_deleted && deletedFieldName != null) { | ||||||
|  | 			query.append("AND "); | ||||||
|  | 			query.append(tableName); | ||||||
|  | 			query.append("."); | ||||||
|  | 			query.append(deletedFieldName); | ||||||
|  | 			query.append(" = false "); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.GlobalConfiguration; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  | import org.kar.archidata.dataAccess.QueryOptions; | ||||||
|  | import org.kar.archidata.db.DBConfig; | ||||||
|  | import org.kar.archidata.db.DBEntry; | ||||||
|  |  | ||||||
|  | public class DBInterfaceOption extends QueryOption { | ||||||
|  | 	private DBEntry entry = null; | ||||||
|  | 	private final DBConfig config; | ||||||
|  | 	private final boolean root; | ||||||
|  | 	 | ||||||
|  | 	public DBInterfaceOption(final DBConfig config) { | ||||||
|  | 		this.config = config; | ||||||
|  | 		this.root = false; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public DBInterfaceOption(final DBConfig config, boolean root) { | ||||||
|  | 		this.config = config; | ||||||
|  | 		this.root = root; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public DBEntry getEntry(QueryOptions options) throws IOException { | ||||||
|  | 		if (this.entry == null) { | ||||||
|  | 			final DBInterfaceRoot isRoot = options.get(DBInterfaceRoot.class); | ||||||
|  | 			this.entry = DBEntry.createInterface(this.config, isRoot != null && isRoot.getRoot()); | ||||||
|  | 		} | ||||||
|  | 		return this.entry; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public boolean getRoot() { | ||||||
|  | 		return this.root; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public static DBEntry getAutoEntry(QueryOptions options) throws IOException { | ||||||
|  | 		final DBInterfaceOption dbOption = options.get(DBInterfaceOption.class); | ||||||
|  | 		if (dbOption == null) { | ||||||
|  | 			final DBInterfaceRoot isRoot = options.get(DBInterfaceRoot.class); | ||||||
|  | 			return DBEntry.createInterface(GlobalConfiguration.dbConfig, isRoot != null && isRoot.getRoot()); | ||||||
|  | 		} else { | ||||||
|  | 			return dbOption.getEntry(options); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
| @@ -0,0 +1,16 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  |  | ||||||
|  | public class DBInterfaceRoot extends QueryOption { | ||||||
|  | 	private final boolean root; | ||||||
|  | 	 | ||||||
|  | 	public DBInterfaceRoot(boolean root) { | ||||||
|  | 		this.root = root; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public boolean getRoot() { | ||||||
|  | 		return this.root; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/org/kar/archidata/dataAccess/options/FilterValue.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/org/kar/archidata/dataAccess/options/FilterValue.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  |  | ||||||
|  | /** By default some element are not read like createAt and UpdatedAt. This option permit to read it. */ | ||||||
|  | public class FilterValue extends QueryOption { | ||||||
|  | 	public final List<String> filterValue; | ||||||
|  |  | ||||||
|  | 	public FilterValue(final List<String> filterValue) { | ||||||
|  | 		this.filterValue = filterValue; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public FilterValue(final String... filterValue) { | ||||||
|  | 		this.filterValue = List.of(filterValue); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public List<String> getValues() { | ||||||
|  | 		return this.filterValue; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| package org.kar.archidata.dataAccess.options; |  | ||||||
|  |  | ||||||
| import org.kar.archidata.dataAccess.QueryOption; |  | ||||||
|  |  | ||||||
| /** Option that permit to access to a table structure with an other name that is define in the structure. Note: Internal use for link tables (see: |  | ||||||
|  * org.kar.archidata.dataAccess.addOn.model.LinkTable). */ |  | ||||||
| public class Limit extends QueryOption { |  | ||||||
| 	private final int limit; |  | ||||||
|  |  | ||||||
| 	public Limit(final int limit) { |  | ||||||
| 		this.limit = limit; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public int getLimit() { |  | ||||||
| 		return this.limit; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										16
									
								
								src/org/kar/archidata/dataAccess/options/TransmitKey.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/org/kar/archidata/dataAccess/options/TransmitKey.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | package org.kar.archidata.dataAccess.options; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.dataAccess.QueryOption; | ||||||
|  |  | ||||||
|  | /** Internal option that permit to transmit the Key when updating the ManyToMany values (first step). */ | ||||||
|  | public class TransmitKey extends QueryOption { | ||||||
|  | 	private final Object key; | ||||||
|  |  | ||||||
|  | 	public TransmitKey(final Object key) { | ||||||
|  | 		this.key = key; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public Object getKey() { | ||||||
|  | 		return this.key; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -52,7 +52,7 @@ public class DBEntry implements Closeable { | |||||||
| 		try { | 		try { | ||||||
| 			this.connection = DriverManager.getConnection(this.config.getUrl(true), this.config.getLogin(), this.config.getPassword()); | 			this.connection = DriverManager.getConnection(this.config.getUrl(true), this.config.getLogin(), this.config.getPassword()); | ||||||
| 		} catch (final SQLException ex) { | 		} catch (final SQLException ex) { | ||||||
| 			throw new IOException("Connection db fail: " + ex.getMessage()); | 			throw new IOException("Connection db fail: " + ex.getMessage() + " On URL: " + this.config.getUrl(true)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
| @@ -61,7 +61,7 @@ public class DBEntry implements Closeable { | |||||||
| 		try { | 		try { | ||||||
| 			this.connection = DriverManager.getConnection(this.config.getUrl(), this.config.getLogin(), this.config.getPassword()); | 			this.connection = DriverManager.getConnection(this.config.getUrl(), this.config.getLogin(), this.config.getPassword()); | ||||||
| 		} catch (final SQLException ex) { | 		} catch (final SQLException ex) { | ||||||
| 			throw new IOException("Connection db fail: " + ex.getMessage()); | 			throw new IOException("Connection db fail: " + ex.getMessage() + " On URL: " + this.config.getUrl(true)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -38,13 +38,13 @@ import jakarta.ws.rs.ext.Provider; | |||||||
| @Provider | @Provider | ||||||
| @Priority(Priorities.AUTHENTICATION) | @Priority(Priorities.AUTHENTICATION) | ||||||
| public class AuthenticationFilter implements ContainerRequestFilter { | public class AuthenticationFilter implements ContainerRequestFilter { | ||||||
| 	final Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class); | 	private final static Logger LOGGER = LoggerFactory.getLogger(AuthenticationFilter.class); | ||||||
| 	@Context | 	@Context | ||||||
| 	private ResourceInfo resourceInfo; | 	private ResourceInfo resourceInfo; | ||||||
| 	protected final String applicationName; | 	protected final String applicationName; | ||||||
|  |  | ||||||
| 	private static final String AUTHENTICATION_SCHEME = "Yota"; | 	public static final String AUTHENTICATION_SCHEME = "Bearer"; | ||||||
| 	private static final String AUTHENTICATION_TOKEN_SCHEME = "Zota"; | 	public static final String APIKEY = "ApiKey"; | ||||||
|  |  | ||||||
| 	public AuthenticationFilter(final String applicationName) { | 	public AuthenticationFilter(final String applicationName) { | ||||||
| 		this.applicationName = applicationName; | 		this.applicationName = applicationName; | ||||||
| @@ -57,8 +57,8 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		final Method method = this.resourceInfo.getResourceMethod(); | 		final Method method = this.resourceInfo.getResourceMethod(); | ||||||
| 		// Access denied for all | 		// Access denied for all | ||||||
| 		if (method.isAnnotationPresent(DenyAll.class)) { | 		if (method.isAnnotationPresent(DenyAll.class)) { | ||||||
| 			this.logger.debug("   ==> deny all {}", requestContext.getUriInfo().getPath()); | 			LOGGER.debug("   ==> deny all {}", requestContext.getUriInfo().getPath()); | ||||||
| 			requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access blocked !!!").build()); | 			abortWithForbidden(requestContext, "Access blocked !!!"); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -70,64 +70,62 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		} | 		} | ||||||
| 		// this is a security guard, all the API must define their access level: | 		// this is a security guard, all the API must define their access level: | ||||||
| 		if (!method.isAnnotationPresent(RolesAllowed.class)) { | 		if (!method.isAnnotationPresent(RolesAllowed.class)) { | ||||||
| 			this.logger.error("   ==> missing @RolesAllowed {}", requestContext.getUriInfo().getPath()); | 			LOGGER.error("   ==> missing @RolesAllowed {}", requestContext.getUriInfo().getPath()); | ||||||
| 			requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Access ILLEGAL !!!").build()); | 			abortWithForbidden(requestContext, "Access ILLEGAL !!!"); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Get the Authorization header from the request | 		// Get the Authorization header from the request | ||||||
| 		String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); | 		String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); | ||||||
|  | 		String apikeyHeader = requestContext.getHeaderString(APIKEY); | ||||||
| 		// logger.debug("authorizationHeader: {}", authorizationHeader); | 		// logger.debug("authorizationHeader: {}", authorizationHeader); | ||||||
| 		if (authorizationHeader == null && method.isAnnotationPresent(PermitTokenInURI.class)) { | 		if (authorizationHeader == null && apikeyHeader == null && method.isAnnotationPresent(PermitTokenInURI.class)) { | ||||||
| 			final MultivaluedMap<String, String> quaryparam = requestContext.getUriInfo().getQueryParameters(); | 			final MultivaluedMap<String, String> quaryparam = requestContext.getUriInfo().getQueryParameters(); | ||||||
| 			for (final Entry<String, List<String>> item : quaryparam.entrySet()) { | 			for (final Entry<String, List<String>> item : quaryparam.entrySet()) { | ||||||
| 				if (item.getKey().equals(HttpHeaders.AUTHORIZATION)) { | 				if ((authorizationHeader == null && HttpHeaders.AUTHORIZATION.equals(item.getKey())) && !item.getValue().isEmpty()) { | ||||||
| 					if (!item.getValue().isEmpty()) { |  | ||||||
| 					authorizationHeader = item.getValue().get(0); | 					authorizationHeader = item.getValue().get(0); | ||||||
| 				} | 				} | ||||||
| 					break; | 				if ((apikeyHeader == null && APIKEY.equals(item.getKey())) && !item.getValue().isEmpty()) { | ||||||
|  | 					apikeyHeader = item.getValue().get(0); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// logger.debug("authorizationHeader: {}", authorizationHeader); | 		// logger.debug("authorizationHeader: {}", authorizationHeader); | ||||||
| 		final boolean isApplicationToken = isApplicationTokenBasedAuthentication(authorizationHeader); | 		final boolean isApplicationToken = apikeyHeader != null; | ||||||
| 		final boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader); | 		final boolean isJwtToken = isTokenBasedAuthentication(authorizationHeader); | ||||||
| 		// Validate the Authorization header data Model "Yota jwt.to.ken" "Zota tokenId:hash(token)" |  | ||||||
| 		if (!isApplicationToken && !isJwtToken) { | 		if (!isApplicationToken && !isJwtToken) { | ||||||
| 			this.logger.warn("REJECTED unauthorized: {}", requestContext.getUriInfo().getPath()); | 			LOGGER.warn("REJECTED unauthorized: {}", requestContext.getUriInfo().getPath()); | ||||||
| 			abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath()); | 			abortWithUnauthorized(requestContext, "REJECTED unauthorized: " + requestContext.getUriInfo().getPath()); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 		UserByToken userByToken = null; | 		UserByToken userByToken = null; | ||||||
| 		if (isJwtToken) { | 		if (isJwtToken) { | ||||||
| 			// Extract the token from the Authorization header (Remove "Yota ") | 			// Extract the token from the Authorization header (Remove "Bearer ") | ||||||
| 			final String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim(); | 			final String token = authorizationHeader.substring(AUTHENTICATION_SCHEME.length()).trim(); | ||||||
| 			// logger.debug("token: {}", token); | 			// logger.debug("token: {}", token); | ||||||
| 			try { | 			try { | ||||||
| 				userByToken = validateJwtToken(token); | 				userByToken = validateJwtToken(token); | ||||||
| 			} catch (final Exception e) { | 			} catch (final Exception e) { | ||||||
| 				this.logger.error("Fail to validate token: {}", e.getMessage()); | 				LOGGER.error("Fail to validate token: {}", e.getMessage()); | ||||||
| 				abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage()); | 				abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage()); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			if (userByToken == null) { | 			if (userByToken == null) { | ||||||
| 				this.logger.warn("get a NULL user ..."); | 				LOGGER.warn("get a NULL user ..."); | ||||||
| 				abortWithUnauthorized(requestContext, "get a NULL user ..."); | 				abortWithUnauthorized(requestContext, "get a NULL user ..."); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			// Extract the token from the Authorization header (Remove "Zota ") | 			final String token = apikeyHeader.trim(); | ||||||
| 			final String token = authorizationHeader.substring(AUTHENTICATION_TOKEN_SCHEME.length()).trim(); |  | ||||||
| 			// logger.debug("token: {}", token); |  | ||||||
| 			try { | 			try { | ||||||
| 				userByToken = validateToken(token); | 				userByToken = validateToken(token); | ||||||
| 			} catch (final Exception e) { | 			} catch (final Exception e) { | ||||||
| 				this.logger.error("Fail to validate token: {}", e.getMessage()); | 				LOGGER.error("Fail to validate token: {}", e.getMessage()); | ||||||
| 				abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage()); | 				abortWithUnauthorized(requestContext, "Fail to validate token: " + e.getMessage()); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| 			if (userByToken == null) { | 			if (userByToken == null) { | ||||||
| 				this.logger.warn("get a NULL application ..."); | 				LOGGER.warn("get a NULL application ..."); | ||||||
| 				abortWithUnauthorized(requestContext, "get a NULL application ..."); | 				abortWithUnauthorized(requestContext, "get a NULL application ..."); | ||||||
| 				return; | 				return; | ||||||
| 			} | 			} | ||||||
| @@ -149,7 +147,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		} | 		} | ||||||
| 		// Is user valid? | 		// Is user valid? | ||||||
| 		if (!haveRight) { | 		if (!haveRight) { | ||||||
| 			this.logger.error("REJECTED not enought right : {} require: {}", requestContext.getUriInfo().getPath(), roles); | 			LOGGER.error("REJECTED not enought right : {} require: {}", requestContext.getUriInfo().getPath(), roles); | ||||||
| 			requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Not enought RIGHT !!!").build()); | 			requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Not enought RIGHT !!!").build()); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| @@ -164,26 +162,25 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " "); | 		return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " "); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private boolean isApplicationTokenBasedAuthentication(final String authorizationHeader) { |  | ||||||
| 		// Check if the Authorization header is valid |  | ||||||
| 		// It must not be null and must be prefixed with "Bearer" plus a whitespace |  | ||||||
| 		// The authentication scheme comparison must be case-insensitive |  | ||||||
| 		return authorizationHeader != null && authorizationHeader.toLowerCase().startsWith(AUTHENTICATION_TOKEN_SCHEME.toLowerCase() + " "); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void abortWithUnauthorized(final ContainerRequestContext requestContext, final String message) { | 	private void abortWithUnauthorized(final ContainerRequestContext requestContext, final String message) { | ||||||
|  |  | ||||||
| 		// Abort the filter chain with a 401 status code response | 		// Abort the filter chain with a 401 status code response | ||||||
| 		// The WWW-Authenticate header is sent along with the response | 		// The WWW-Authenticate header is sent along with the response | ||||||
| 		this.logger.warn("abortWithUnauthorized:"); | 		LOGGER.warn("abortWithUnauthorized:"); | ||||||
| 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message); | 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.UNAUTHORIZED, "Unauthorized", message); | ||||||
| 		this.logger.error("Error UUID={}", ret.uuid); | 		LOGGER.error("Error UUID={}", ret.uuid); | ||||||
| 		requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)").entity(ret) | 		requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, AUTHENTICATION_SCHEME + " base64(HEADER).base64(CONTENT).base64(KEY)").entity(ret) | ||||||
| 				.type(MediaType.APPLICATION_JSON).build()); | 				.type(MediaType.APPLICATION_JSON).build()); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	private void abortWithForbidden(final ContainerRequestContext requestContext, final String message) { | ||||||
|  | 		final RestErrorResponse ret = new RestErrorResponse(Response.Status.FORBIDDEN, "FORBIDDEN", message); | ||||||
|  | 		LOGGER.error("Error UUID={}", ret.uuid); | ||||||
|  | 		requestContext.abortWith(Response.status(ret.status).header(HttpHeaders.WWW_AUTHENTICATE, message).entity(ret).type(MediaType.APPLICATION_JSON).build()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	protected UserByToken validateToken(final String authorization) throws Exception { | 	protected UserByToken validateToken(final String authorization) throws Exception { | ||||||
| 		this.logger.info("Must be Override by the application implmentation, otherwise it dose not work"); | 		LOGGER.info("Must be Override by the application implmentation, otherwise it dose not work"); | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -193,7 +190,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 		final JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null); | 		final JWTClaimsSet ret = JWTWrapper.validateToken(authorization, "KarAuth", null); | ||||||
| 		// check the token is valid !!! (signed and coherent issuer... | 		// check the token is valid !!! (signed and coherent issuer... | ||||||
| 		if (ret == null) { | 		if (ret == null) { | ||||||
| 			this.logger.error("The token is not valid: '{}'", authorization); | 			LOGGER.error("The token is not valid: '{}'", authorization); | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
| 		// check userID | 		// check userID | ||||||
| @@ -209,7 +206,7 @@ public class AuthenticationFilter implements ContainerRequestFilter { | |||||||
| 			if (rights.containsKey(this.applicationName)) { | 			if (rights.containsKey(this.applicationName)) { | ||||||
| 				user.right = rights.get(this.applicationName); | 				user.right = rights.get(this.applicationName); | ||||||
| 			} else { | 			} else { | ||||||
| 				this.logger.error("Connect with no right for this application='{}' full Right='{}'", this.applicationName, rights); | 				LOGGER.error("Connect with no right for this application='{}' full Right='{}'", this.applicationName, rights); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		// logger.debug("request user: '{}' right: '{}' row='{}'", userUID, user.right, rowRight); | 		// logger.debug("request user: '{}' right: '{}' row='{}'", userUID, user.right, rowRight); | ||||||
|   | |||||||
| @@ -18,6 +18,6 @@ public class CORSFilter implements ContainerResponseFilter { | |||||||
| 		response.getHeaders().add("Access-Control-Allow-Headers", "*"); | 		response.getHeaders().add("Access-Control-Allow-Headers", "*"); | ||||||
| 		// "Origin, content-type, Content-type, Accept, authorization, mime-type, filename"); | 		// "Origin, content-type, Content-type, Accept, authorization, mime-type, filename"); | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Credentials", "true"); | 		response.getHeaders().add("Access-Control-Allow-Credentials", "true"); | ||||||
| 		response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); | 		response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD"); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,13 +35,13 @@ class MySecurityContext implements SecurityContext { | |||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean isSecure() { | 	public boolean isSecure() { | ||||||
| 		return this.sheme.equalsIgnoreCase("https"); | 		return "https".equalsIgnoreCase(this.sheme); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public String getAuthenticationScheme() { | 	public String getAuthenticationScheme() { | ||||||
| 		if (this.contextPrincipale.userByToken != null) { | 		if (this.contextPrincipale.userByToken != null) { | ||||||
| 			return "Zota"; | 			return "Bearer"; | ||||||
| 		} | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ public class MigrationEngine { | |||||||
| 		try { | 		try { | ||||||
| 			List<Migration> data = null; | 			List<Migration> data = null; | ||||||
| 			try { | 			try { | ||||||
| 				data = DataAccess.gets(Migration.class, new QueryOptions(QueryOptions.READ_ALL_COLOMN)); | 				data = DataAccess.gets(Migration.class, QueryOptions.READ_ALL_COLOMN); | ||||||
| 			} catch (final Exception e) { | 			} catch (final Exception e) { | ||||||
| 				// Previous version does not have the same timeCode... | 				// Previous version does not have the same timeCode... | ||||||
| 				data = DataAccess.gets(Migration.class); | 				data = DataAccess.gets(Migration.class); | ||||||
|   | |||||||
| @@ -105,9 +105,8 @@ public class MigrationSqlStep implements MigrationInterface { | |||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
| 			} | 			} | ||||||
| 			try { | 			try { | ||||||
| 				Thread.sleep(100); | 				Thread.sleep(2); | ||||||
| 			} catch (final InterruptedException e) { | 			} catch (final InterruptedException e) { | ||||||
| 				// TODO Auto-generated catch block |  | ||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -1,34 +1,41 @@ | |||||||
| package org.kar.archidata.migration.model; | package org.kar.archidata.migration.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataComment; |  | ||||||
| import org.kar.archidata.annotation.DataDefault; | import org.kar.archidata.annotation.DataDefault; | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.annotation.DataNotRead; | ||||||
| import org.kar.archidata.model.GenericDataSoftDelete; | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
| // For logs only | // For logs only | ||||||
| //public static final String TABLE_NAME = "KAR_migration"; | //public static final String TABLE_NAME = "KAR_migration"; | ||||||
|  |  | ||||||
|  | // TODO: Add a migration Hash to be sure that the current migration init is correct and has not change... | ||||||
| @Table(name = "KAR_migration") | @Table(name = "KAR_migration") | ||||||
| @DataIfNotExists | @DataIfNotExists | ||||||
| @JsonInclude(JsonInclude.Include.NON_NULL) | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
| public class Migration extends GenericDataSoftDelete { | public class Migration extends GenericDataSoftDelete { | ||||||
| 	@DataComment("Name of the migration") | 	final static int VERSION_MIGRATION = 2; | ||||||
|  | 	@Schema(description = "Name of the migration") | ||||||
| 	@Column(length = 256) | 	@Column(length = 256) | ||||||
| 	public String name; | 	public String name; | ||||||
|  | 	@DataNotRead | ||||||
|  | 	@DataDefault("'2'") | ||||||
|  | 	@Schema(description = "Version of the migration engine") | ||||||
|  | 	public Integer version; | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	@DataDefault("'0'") | 	@DataDefault("'0'") | ||||||
| 	@DataComment("if the migration is well terminated or not") | 	@Schema(description = "if the migration is well terminated or not") | ||||||
| 	public Boolean terminated = false; | 	public Boolean terminated = false; | ||||||
| 	@DataComment("index in the migration progression") | 	@Schema(description = "index in the migration progression") | ||||||
| 	public Integer stepId = 0; | 	public Integer stepId = 0; | ||||||
| 	@DataComment("number of element in the migration") | 	@Schema(description = "number of element in the migration") | ||||||
| 	public Integer count; | 	public Integer count; | ||||||
| 	@DataComment("Log generate by the migration") | 	@Schema(description = "Log generate by the migration") | ||||||
| 	@Column(length = 0) | 	@Column(length = -1) | ||||||
| 	public String log = ""; | 	public String log = ""; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										35
									
								
								src/org/kar/archidata/migration/model/Migration1.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/org/kar/archidata/migration/model/Migration1.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | package org.kar.archidata.migration.model; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.DataDefault; | ||||||
|  | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  | import org.kar.archidata.model.GenericDataSoftDelete; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.persistence.Column; | ||||||
|  | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
|  | // For logs only | ||||||
|  | //public static final String TABLE_NAME = "KAR_migration"; | ||||||
|  |  | ||||||
|  | @Table(name = "KAR_migration") | ||||||
|  | @DataIfNotExists | ||||||
|  | @JsonInclude(JsonInclude.Include.NON_NULL) | ||||||
|  | public class Migration1 extends GenericDataSoftDelete { | ||||||
|  | 	final static int VERSION_MIGRATION = 1; | ||||||
|  | 	@Schema(description = "Name of the migration") | ||||||
|  | 	@Column(length = 256) | ||||||
|  | 	public String name; | ||||||
|  | 	@Column(nullable = false) | ||||||
|  | 	@DataDefault("'0'") | ||||||
|  | 	@Schema(description = "if the migration is well terminated or not") | ||||||
|  | 	public Boolean terminated = false; | ||||||
|  | 	@Schema(description = "index in the migration progression") | ||||||
|  | 	public Integer stepId = 0; | ||||||
|  | 	@Schema(description = "number of element in the migration") | ||||||
|  | 	public Integer count; | ||||||
|  | 	@Schema(description = "Log generate by the migration") | ||||||
|  | 	@Column(length = 0) | ||||||
|  | 	public String log = ""; | ||||||
|  | } | ||||||
| @@ -1,10 +1,10 @@ | |||||||
| package org.kar.archidata.model; | package org.kar.archidata.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataComment; |  | ||||||
| import org.kar.archidata.annotation.DataIfNotExists; | import org.kar.archidata.annotation.DataIfNotExists; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonInclude; | import com.fasterxml.jackson.annotation.JsonInclude; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||||
|  |  | ||||||
| @@ -14,12 +14,12 @@ import jakarta.persistence.Table; | |||||||
| public class Data extends GenericDataSoftDelete { | public class Data extends GenericDataSoftDelete { | ||||||
|  |  | ||||||
| 	@Column(length = 128, nullable = false) | 	@Column(length = 128, nullable = false) | ||||||
| 	@DataComment("Sha512 of the data") | 	@Schema(description = "Sha512 of the data") | ||||||
| 	public String sha512; | 	public String sha512; | ||||||
| 	@Column(length = 128, nullable = false) | 	@Column(length = 128, nullable = false) | ||||||
| 	@DataComment("Mime -type of the media") | 	@Schema(description = "Mime -type of the media") | ||||||
| 	public String mimeType; | 	public String mimeType; | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	@DataComment("Size in Byte of the data") | 	@Schema(description = "Size in Byte of the data") | ||||||
| 	public Long size; | 	public Long size; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,33 +3,36 @@ package org.kar.archidata.model; | |||||||
| import java.util.Date; | import java.util.Date; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.CreationTimestamp; | import org.kar.archidata.annotation.CreationTimestamp; | ||||||
| import org.kar.archidata.annotation.DataComment; |  | ||||||
| import org.kar.archidata.annotation.DataNotRead; | import org.kar.archidata.annotation.DataNotRead; | ||||||
| import org.kar.archidata.annotation.UpdateTimestamp; | import org.kar.archidata.annotation.UpdateTimestamp; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
| import jakarta.persistence.GeneratedValue; | import jakarta.persistence.GeneratedValue; | ||||||
| import jakarta.persistence.GenerationType; | import jakarta.persistence.GenerationType; | ||||||
| import jakarta.persistence.Id; | import jakarta.persistence.Id; | ||||||
| import jakarta.persistence.Temporal; | import jakarta.persistence.Temporal; | ||||||
| import jakarta.persistence.TemporalType; | import jakarta.persistence.TemporalType; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  |  | ||||||
| public class GenericData { | public class GenericData { | ||||||
| 	@Id | 	@Id | ||||||
| 	@GeneratedValue(strategy = GenerationType.IDENTITY) | 	@GeneratedValue(strategy = GenerationType.IDENTITY) | ||||||
| 	@Column(nullable = false, unique = true) | 	@Column(nullable = false, unique = true) | ||||||
| 	@DataComment("Primary key of the base") | 	@Schema(description = "Unique Id of the object", required = false, readOnly = true, example = "123456") | ||||||
| 	public Long id = null; | 	public Long id = null; | ||||||
| 	@DataNotRead | 	@DataNotRead | ||||||
| 	@CreationTimestamp | 	@CreationTimestamp | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	@Temporal(TemporalType.TIMESTAMP) | 	@Temporal(TemporalType.TIMESTAMP) | ||||||
| 	@DataComment("Create time of the object") | 	@NotNull | ||||||
|  | 	@Schema(description = "Create time of the object", required = false, example = "2000-01-23T01:23:45.678+01:00", readOnly = true) | ||||||
| 	public Date createdAt = null; | 	public Date createdAt = null; | ||||||
| 	@DataNotRead | 	@DataNotRead | ||||||
| 	@UpdateTimestamp | 	@UpdateTimestamp | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	@Temporal(TemporalType.TIMESTAMP) | 	@Temporal(TemporalType.TIMESTAMP) | ||||||
| 	@DataComment("When update the object") | 	@NotNull | ||||||
|  | 	@Schema(description = "When update the object", required = false, example = "2000-01-23T00:23:45.678Z", readOnly = true) | ||||||
| 	public Date updatedAt = null; | 	public Date updatedAt = null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,17 +1,19 @@ | |||||||
| package org.kar.archidata.model; | package org.kar.archidata.model; | ||||||
|  |  | ||||||
| import org.kar.archidata.annotation.DataComment; |  | ||||||
| import org.kar.archidata.annotation.DataDefault; | import org.kar.archidata.annotation.DataDefault; | ||||||
| import org.kar.archidata.annotation.DataDeleted; | import org.kar.archidata.annotation.DataDeleted; | ||||||
| import org.kar.archidata.annotation.DataNotRead; | import org.kar.archidata.annotation.DataNotRead; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
| import jakarta.persistence.Column; | import jakarta.persistence.Column; | ||||||
|  | import jakarta.validation.constraints.NotNull; | ||||||
|  |  | ||||||
| public class GenericDataSoftDelete extends GenericData { | public class GenericDataSoftDelete extends GenericData { | ||||||
| 	@DataNotRead | 	@DataNotRead | ||||||
| 	@Column(nullable = false) | 	@Column(nullable = false) | ||||||
| 	@DataDefault("'0'") | 	@DataDefault("'0'") | ||||||
| 	@DataDeleted | 	@DataDeleted | ||||||
| 	@DataComment("When delete, they are not removed, they are just set in a deleted state") | 	@NotNull | ||||||
|  | 	@Schema(description = "Deleted state", hidden = true, required = false, readOnly = true) | ||||||
| 	public Boolean deleted = null; | 	public Boolean deleted = null; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								src/org/kar/archidata/serializer/CSVMessageBodyWritter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/org/kar/archidata/serializer/CSVMessageBodyWritter.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | package org.kar.archidata.serializer; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.lang.annotation.Annotation; | ||||||
|  | import java.lang.reflect.Type; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.dataformat.csv.CsvMapper; | ||||||
|  | import com.fasterxml.jackson.dataformat.csv.CsvSchema; | ||||||
|  |  | ||||||
|  | import jakarta.ws.rs.Produces; | ||||||
|  | import jakarta.ws.rs.WebApplicationException; | ||||||
|  | import jakarta.ws.rs.core.MediaType; | ||||||
|  | import jakarta.ws.rs.core.MultivaluedMap; | ||||||
|  | import jakarta.ws.rs.ext.MessageBodyWriter; | ||||||
|  | import jakarta.ws.rs.ext.Provider; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Body writter use in jersey with : | ||||||
|  |  * In your main: | ||||||
|  |  * ```java | ||||||
|  |  * rc.register(new CSVMessageBodyWritter()); | ||||||
|  |  * ``` | ||||||
|  |  * | ||||||
|  |  * and in the produce element: | ||||||
|  |  * ```java | ||||||
|  |  * @GET | ||||||
|  |  * @Produces("text/csv") | ||||||
|  |  * public List<Data> getData() {} | ||||||
|  |  * ``` | ||||||
|  |  */ | ||||||
|  | @Provider | ||||||
|  | @Produces("text/csv") | ||||||
|  | public class CSVMessageBodyWritter implements MessageBodyWriter<List<?>> { | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { | ||||||
|  | 		return List.class.isAssignableFrom(type); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public long getSize(List<?> data, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public void writeTo(List<?> data, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) | ||||||
|  | 			throws IOException, WebApplicationException { | ||||||
|  | 		if (data != null && data.size() > 0) { | ||||||
|  | 			CsvMapper mapper = new CsvMapper(); | ||||||
|  | 			Object o = data.get(0); | ||||||
|  | 			CsvSchema schema = mapper.schemaFor(o.getClass()).withHeader(); | ||||||
|  | 			mapper.writer(schema).writeValue(entityStream, data); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -14,6 +14,9 @@ public class ConfigBaseVariable { | |||||||
| 	static public String ssoAdress; | 	static public String ssoAdress; | ||||||
| 	static public String ssoToken; | 	static public String ssoToken; | ||||||
| 	static public String testMode; | 	static public String testMode; | ||||||
|  | 	static public String eMailFrom; | ||||||
|  | 	static public String eMailLogin; | ||||||
|  | 	static public String eMailPassword; | ||||||
|  |  | ||||||
| 	// For test only | 	// For test only | ||||||
| 	public static void clearAllValue() { | 	public static void clearAllValue() { | ||||||
| @@ -30,6 +33,9 @@ public class ConfigBaseVariable { | |||||||
| 		ssoAdress = System.getenv("SSO_ADDRESS"); | 		ssoAdress = System.getenv("SSO_ADDRESS"); | ||||||
| 		ssoToken = System.getenv("SSO_TOKEN"); | 		ssoToken = System.getenv("SSO_TOKEN"); | ||||||
| 		testMode = System.getenv("TEST_MODE"); | 		testMode = System.getenv("TEST_MODE"); | ||||||
|  | 		eMailFrom = System.getenv("EMAIL_FROM"); | ||||||
|  | 		eMailLogin = System.getenv("EMAIL_LOGIN"); | ||||||
|  | 		eMailPassword = System.getenv("EMAIL_PASSWORD"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static { | 	static { | ||||||
| @@ -120,4 +126,15 @@ public class ConfigBaseVariable { | |||||||
| 		} | 		} | ||||||
| 		return Boolean.parseBoolean(testMode); | 		return Boolean.parseBoolean(testMode); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public record EMailConfig(String from, String login, String password) { | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	public static EMailConfig getEMailConfig() { | ||||||
|  | 		if (eMailFrom == null || eMailLogin == null || eMailPassword == null) { | ||||||
|  | 			return null; | ||||||
|  | 		} | ||||||
|  | 		return new EMailConfig(eMailFrom, eMailLogin, eMailPassword); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ import org.kar.archidata.dataAccess.DataAccess; | |||||||
| import org.kar.archidata.dataAccess.QueryAnd; | import org.kar.archidata.dataAccess.QueryAnd; | ||||||
| import org.kar.archidata.dataAccess.QueryCondition; | import org.kar.archidata.dataAccess.QueryCondition; | ||||||
| import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | import org.kar.archidata.dataAccess.addOn.AddOnManyToMany; | ||||||
|  | import org.kar.archidata.dataAccess.options.Condition; | ||||||
| import org.kar.archidata.model.Data; | import org.kar.archidata.model.Data; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| @@ -75,7 +76,7 @@ public class DataTools { | |||||||
|  |  | ||||||
| 	public static Data getWithSha512(final String sha512) { | 	public static Data getWithSha512(final String sha512) { | ||||||
| 		try { | 		try { | ||||||
| 			return DataAccess.getWhere(Data.class, new QueryCondition("sha512", "=", sha512)); | 			return DataAccess.getWhere(Data.class, new Condition(new QueryCondition("sha512", "=", sha512))); | ||||||
| 		} catch (final Exception e) { | 		} catch (final Exception e) { | ||||||
| 			// TODO Auto-generated catch block | 			// TODO Auto-generated catch block | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| @@ -85,7 +86,7 @@ public class DataTools { | |||||||
|  |  | ||||||
| 	public static Data getWithId(final long id) { | 	public static Data getWithId(final long id) { | ||||||
| 		try { | 		try { | ||||||
| 			return DataAccess.getWhere(Data.class, new QueryAnd(List.of(new QueryCondition("deleted", "=", false), new QueryCondition("id", "=", id)))); | 			return DataAccess.getWhere(Data.class, new Condition(new QueryAnd(List.of(new QueryCondition("deleted", "=", false), new QueryCondition("id", "=", id))))); | ||||||
| 		} catch (final Exception e) { | 		} catch (final Exception e) { | ||||||
| 			// TODO Auto-generated catch block | 			// TODO Auto-generated catch block | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| @@ -109,15 +110,12 @@ public class DataTools { | |||||||
| 		final String tmpPath = getTmpFileInData(tmpUID); | 		final String tmpPath = getTmpFileInData(tmpUID); | ||||||
| 		final long fileSize = Files.size(Paths.get(tmpPath)); | 		final long fileSize = Files.size(Paths.get(tmpPath)); | ||||||
| 		Data out = new Data(); | 		Data out = new Data(); | ||||||
| 		; |  | ||||||
| 		try { | 		try { | ||||||
| 			out.sha512 = sha512; | 			out.sha512 = sha512; | ||||||
| 			out.mimeType = mimeType; | 			out.mimeType = mimeType; | ||||||
| 			out.size = fileSize; | 			out.size = fileSize; | ||||||
| 			out = DataAccess.insert(out); | 			out = DataAccess.insert(out); | ||||||
| 		} catch (final SQLException ex) { |  | ||||||
| 			ex.printStackTrace(); |  | ||||||
| 			return null; |  | ||||||
| 		} catch (final Exception e) { | 		} catch (final Exception e) { | ||||||
| 			// TODO Auto-generated catch block | 			// TODO Auto-generated catch block | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import java.util.Map; | |||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.filter.AuthenticationFilter; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| @@ -51,20 +52,20 @@ class TestSigner implements JWSSigner { | |||||||
| 	@Override | 	@Override | ||||||
| 	public Set<JWSAlgorithm> supportedJWSAlgorithms() { | 	public Set<JWSAlgorithm> supportedJWSAlgorithms() { | ||||||
| 		// TODO Auto-generated method stub | 		// TODO Auto-generated method stub | ||||||
| 		return null; | 		return Set.of(JWSAlgorithm.RS256); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	@Override | 	@Override | ||||||
| 	public JCAContext getJCAContext() { | 	public JCAContext getJCAContext() { | ||||||
| 		// TODO Auto-generated method stub | 		// TODO Auto-generated method stub | ||||||
| 		return null; | 		return new JCAContext(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| public class JWTWrapper { | public class JWTWrapper { | ||||||
| 	static final Logger LOGGER = LoggerFactory.getLogger(JWTWrapper.class); | 	static final Logger LOGGER = LoggerFactory.getLogger(JWTWrapper.class); | ||||||
|  |  | ||||||
| 	private static RSAKey rsaJWK = null;; | 	private static RSAKey rsaJWK = null; | ||||||
| 	private static RSAKey rsaPublicJWK = null; | 	private static RSAKey rsaPublicJWK = null; | ||||||
|  |  | ||||||
| 	public static class PublicKey { | 	public static class PublicKey { | ||||||
| @@ -89,7 +90,7 @@ public class JWTWrapper { | |||||||
| 		con.setRequestProperty("Accept", "application/json"); | 		con.setRequestProperty("Accept", "application/json"); | ||||||
| 		final String ssoToken = ConfigBaseVariable.ssoToken(); | 		final String ssoToken = ConfigBaseVariable.ssoToken(); | ||||||
| 		if (ssoToken != null) { | 		if (ssoToken != null) { | ||||||
| 			con.setRequestProperty("Authorization", "Zota " + ssoToken); | 			con.setRequestProperty(AuthenticationFilter.APIKEY, ssoToken); | ||||||
| 		} | 		} | ||||||
| 		final int responseCode = con.getResponseCode(); | 		final int responseCode = con.getResponseCode(); | ||||||
|  |  | ||||||
| @@ -209,8 +210,9 @@ public class JWTWrapper { | |||||||
| 		try { | 		try { | ||||||
| 			// On the consumer side, parse the JWS and verify its RSA signature | 			// On the consumer side, parse the JWS and verify its RSA signature | ||||||
| 			final SignedJWT signedJWT = SignedJWT.parse(signedToken); | 			final SignedJWT signedJWT = SignedJWT.parse(signedToken); | ||||||
|  | 			if (ConfigBaseVariable.getTestMode() && signedToken.endsWith(TestSigner.test_signature)) { | ||||||
| 			if (rsaPublicJWK == null) { | 				LOGGER.warn("Someone use a test token: {}", signedToken); | ||||||
|  | 			} else if (rsaPublicJWK == null) { | ||||||
| 				LOGGER.warn("JWT public key is not present !!!"); | 				LOGGER.warn("JWT public key is not present !!!"); | ||||||
| 				if (!ConfigBaseVariable.getTestMode()) { | 				if (!ConfigBaseVariable.getTestMode()) { | ||||||
| 					return null; | 					return null; | ||||||
| @@ -228,7 +230,7 @@ public class JWTWrapper { | |||||||
| 					return null; | 					return null; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if (!new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) { | 			if (!ConfigBaseVariable.getTestMode() && !new Date().before(signedJWT.getJWTClaimsSet().getExpirationTime())) { | ||||||
| 				LOGGER.error("JWT token is expired now = " + new Date() + " with=" + signedJWT.getJWTClaimsSet().getExpirationTime()); | 				LOGGER.error("JWT token is expired now = " + new Date() + " with=" + signedJWT.getJWTClaimsSet().getExpirationTime()); | ||||||
| 				return null; | 				return null; | ||||||
| 			} | 			} | ||||||
| @@ -243,24 +245,22 @@ public class JWTWrapper { | |||||||
| 			// LOGGER.debug("JWT token is verified 'alice' =?= '" + signedJWT.getJWTClaimsSet().getSubject() + "'"); | 			// LOGGER.debug("JWT token is verified 'alice' =?= '" + signedJWT.getJWTClaimsSet().getSubject() + "'"); | ||||||
| 			// LOGGER.debug("JWT token isuer 'https://c2id.com' =?= '" + signedJWT.getJWTClaimsSet().getIssuer() + "'"); | 			// LOGGER.debug("JWT token isuer 'https://c2id.com' =?= '" + signedJWT.getJWTClaimsSet().getIssuer() + "'"); | ||||||
| 			return signedJWT.getJWTClaimsSet(); | 			return signedJWT.getJWTClaimsSet(); | ||||||
| 		} catch (final JOSEException ex) { | 		} catch (final JOSEException | ParseException e) { | ||||||
| 			ex.printStackTrace(); |  | ||||||
| 		} catch (final ParseException e) { |  | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public static String createJwtTestToken(final long userID, final String userLogin, final String isuer, final String application, final Map<String, Object> rights) { | 	public static String createJwtTestToken(final long userID, final String userLogin, final String isuer, final String application, final Map<String, Map<String, Object>> rights) { | ||||||
| 		if (!ConfigBaseVariable.getTestMode()) { | 		if (!ConfigBaseVariable.getTestMode()) { | ||||||
| 			LOGGER.error("Test mode disable !!!!!"); | 			LOGGER.error("Test mode disable !!!!!"); | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
| 			final int timeOutInMunites = 3600 * 24 * 31; | 			final int timeOutInMunites = 3600; | ||||||
|  |  | ||||||
| 			final Date now = new Date(); | 			final Date now = new Date(); | ||||||
| 			final Date expiration = new Date(new Date().getTime() - 60 * timeOutInMunites * 1000 /* millisecond */); | 			final Date expiration = new Date(new Date().getTime() + timeOutInMunites * 1000 /* ms */); | ||||||
|  |  | ||||||
| 			final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)).claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) | 			final JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder().subject(Long.toString(userID)).claim("login", userLogin).claim("application", application).issuer(isuer).issueTime(now) | ||||||
| 					.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning | 					.expirationTime(expiration); // Do not ask why we need a "-" here ... this have no meaning | ||||||
| @@ -278,7 +278,8 @@ public class JWTWrapper { | |||||||
| 			// serialize the output... | 			// serialize the output... | ||||||
| 			return signedJWT.serialize(); | 			return signedJWT.serialize(); | ||||||
| 		} catch (final Exception ex) { | 		} catch (final Exception ex) { | ||||||
| 			LOGGER.error("Can not generate Test Token..."); | 			ex.printStackTrace(); | ||||||
|  | 			LOGGER.error("Can not generate Test Token... {}", ex.getLocalizedMessage()); | ||||||
| 		} | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								src/org/kar/archidata/tools/ListTools.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/org/kar/archidata/tools/ListTools.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | package org.kar.archidata.tools; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | public class ListTools { | ||||||
|  | 	public static boolean checkListIdentical(final List<?> list1, final List<?> list2) { | ||||||
|  | 		if (list1 == list2) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		if (list1 == null) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		if (list1.size() != list2.size()) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		for (int iii = 0; iii < list1.size(); iii++) { | ||||||
|  | 			final Object aaa = list1.get(iii); | ||||||
|  | 			final Object bbb = list2.get(iii); | ||||||
|  | 			if (aaa == bbb) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			if (aaa == null) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 			if (!aaa.equals(bbb)) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -3,6 +3,7 @@ package org.kar.archidata.tools; | |||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.net.URI; | import java.net.URI; | ||||||
| import java.net.http.HttpClient; | import java.net.http.HttpClient; | ||||||
|  | import java.net.http.HttpClient.Version; | ||||||
| import java.net.http.HttpRequest; | import java.net.http.HttpRequest; | ||||||
| import java.net.http.HttpRequest.BodyPublishers; | import java.net.http.HttpRequest.BodyPublishers; | ||||||
| import java.net.http.HttpRequest.Builder; | import java.net.http.HttpRequest.Builder; | ||||||
| @@ -14,8 +15,10 @@ import org.kar.archidata.exception.RESTErrorResponseExeption; | |||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.core.JsonParseException; | ||||||
| import com.fasterxml.jackson.core.type.TypeReference; | import com.fasterxml.jackson.core.type.TypeReference; | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper; | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
|  | import com.fasterxml.jackson.databind.exc.MismatchedInputException; | ||||||
|  |  | ||||||
| import jakarta.ws.rs.core.HttpHeaders; | import jakarta.ws.rs.core.HttpHeaders; | ||||||
|  |  | ||||||
| @@ -23,6 +26,7 @@ public class RESTApi { | |||||||
| 	final static Logger LOGGER = LoggerFactory.getLogger(RESTApi.class); | 	final static Logger LOGGER = LoggerFactory.getLogger(RESTApi.class); | ||||||
| 	final String baseUrl; | 	final String baseUrl; | ||||||
| 	private String token = null; | 	private String token = null; | ||||||
|  | 	final ObjectMapper mapper = new ObjectMapper(); | ||||||
|  |  | ||||||
| 	public RESTApi(final String baseUrl) { | 	public RESTApi(final String baseUrl) { | ||||||
| 		this.baseUrl = baseUrl; | 		this.baseUrl = baseUrl; | ||||||
| @@ -33,152 +37,151 @@ public class RESTApi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> List<T> gets(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T> List<T> gets(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); |  | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1).uri(URI.create(this.baseUrl + urlOffset)); | ||||||
| 		if (this.token != null) { | 		if (this.token != null) { | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); | 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | ||||||
| 		} | 		} | ||||||
| 		final HttpRequest request = requestBuilding.GET().build(); | 		final HttpRequest request = requestBuilding.GET().build(); | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | 			try { | ||||||
| 			throw out; | 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | ||||||
|  | 				throw new RESTErrorResponseExeption(out.uuid, out.time, out.error, out.message, out.status, out.statusMessage); | ||||||
|  | 			} catch (final MismatchedInputException ex) { | ||||||
|  | 				throw new IOException("Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
| 			} | 			} | ||||||
| 		final List<T> out = mapper.readValue(httpResponse.body(), new TypeReference<List<T>>() {}); | 		} | ||||||
| 		return out; | 		return this.mapper.readValue(httpResponse.body(), new TypeReference<List<T>>() {}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T get(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T> T get(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); | 		return modelSendJson("GET", clazz, urlOffset, null); | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); |  | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); |  | ||||||
| 		if (this.token != null) { |  | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); |  | ||||||
| 		} |  | ||||||
| 		final HttpRequest request = requestBuilding.GET().build(); |  | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); |  | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { |  | ||||||
| 			// LOGGER.error("catch error from REST API: {}", httpResponse.body()); |  | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); |  | ||||||
| 			throw new RESTErrorResponseExeption(out.uuid, out.time, out.error, out.message, out.status, out.statusMessage); |  | ||||||
| 		} |  | ||||||
| 		// LOGGER.error("status code: {}", httpResponse.statusCode()); |  | ||||||
| 		// LOGGER.error("data: {}", httpResponse.body()); |  | ||||||
| 		if (clazz.equals(String.class)) { |  | ||||||
| 			return (T) httpResponse.body(); |  | ||||||
| 		} |  | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); |  | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T post(final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T, U> T post(final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); | 		return modelSend("POST", clazz, urlOffset, data); | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); |  | ||||||
| 		final String body = mapper.writeValueAsString(data); |  | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); |  | ||||||
| 		if (this.token != null) { |  | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); |  | ||||||
| 	} | 	} | ||||||
| 		requestBuilding = requestBuilding.header("Content-Type", "application/json"); |  | ||||||
| 		final HttpRequest request = requestBuilding.POST(BodyPublishers.ofString(body)).build(); | 	public <T, U> T postJson(final Class<T> clazz, final String urlOffset, final String body) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		return modelSendJson("POST", clazz, urlOffset, body); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { |  | ||||||
| 			LOGGER.error("status code: {}", httpResponse.statusCode()); |  | ||||||
| 			LOGGER.error("data: {}", httpResponse.body()); |  | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); |  | ||||||
| 			throw out; |  | ||||||
| 		} |  | ||||||
| 		if (clazz.equals(String.class)) { |  | ||||||
| 			return (T) httpResponse.body(); |  | ||||||
| 		} |  | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); |  | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T postMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T> T postMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); | 		return modelSendMap("POST", clazz, urlOffset, data); | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); |  | ||||||
| 		final String body = mapper.writeValueAsString(data); |  | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); |  | ||||||
| 		if (this.token != null) { |  | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); |  | ||||||
| 		} |  | ||||||
| 		requestBuilding = requestBuilding.header("Content-Type", "application/json"); |  | ||||||
| 		final HttpRequest request = requestBuilding.POST(BodyPublishers.ofString(body)).build(); |  | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); |  | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { |  | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); |  | ||||||
| 			throw out; |  | ||||||
| 		} |  | ||||||
| 		if (clazz.equals(String.class)) { |  | ||||||
| 			return (T) httpResponse.body(); |  | ||||||
| 		} |  | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); |  | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T put(final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T, U> T put(final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); | 		return modelSend("PUT", clazz, urlOffset, data); | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); |  | ||||||
| 		final String body = mapper.writeValueAsString(data); |  | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); |  | ||||||
| 		if (this.token != null) { |  | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); |  | ||||||
| 	} | 	} | ||||||
| 		requestBuilding = requestBuilding.header("Content-Type", "application/json"); |  | ||||||
| 		final HttpRequest request = requestBuilding.PUT(BodyPublishers.ofString(body)).build(); | 	public <T, U> T putJson(final Class<T> clazz, final String urlOffset, final String body) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		return modelSendJson("PUT", clazz, urlOffset, body); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { |  | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); |  | ||||||
| 			throw out; |  | ||||||
| 		} |  | ||||||
| 		if (clazz.equals(String.class)) { |  | ||||||
| 			return (T) httpResponse.body(); |  | ||||||
| 		} |  | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); |  | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T> T putMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	public <T> T putMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); | 		return modelSendMap("PUT", clazz, urlOffset, data); | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); |  | ||||||
| 		final String body = mapper.writeValueAsString(data); |  | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); |  | ||||||
| 		if (this.token != null) { |  | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	public <T, U> T patch(final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return modelSend("PATCH", clazz, urlOffset, data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public <T, U> T patchJson(final Class<T> clazz, final String urlOffset, final String body) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return modelSendJson("PATCH", clazz, urlOffset, body); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public <T> T patchMap(final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		return modelSendMap("PATCH", clazz, urlOffset, data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	protected <T, U> T modelSend(final String model, final Class<T> clazz, final String urlOffset, final U data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		if (data == null) { | ||||||
|  | 			return modelSendJson(model, clazz, urlOffset, null); | ||||||
|  | 		} else { | ||||||
|  | 			final String body = this.mapper.writeValueAsString(data); | ||||||
|  | 			return modelSendJson(model, clazz, urlOffset, body); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	protected <T, U> T modelSendJson(final String model, final Class<T> clazz, final String urlOffset, String body) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
|  | 		// client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true); | ||||||
|  | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1).uri(URI.create(this.baseUrl + urlOffset)); | ||||||
|  | 		LOGGER.trace("call {}: {}", model, URI.create(this.baseUrl + urlOffset)); | ||||||
|  | 		LOGGER.trace("DATA: {}", body); | ||||||
|  | 		if (this.token != null) { | ||||||
|  | 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | ||||||
|  | 		} | ||||||
|  | 		if (body == null) { | ||||||
|  | 			body = ""; | ||||||
|  | 		} else { | ||||||
| 			requestBuilding = requestBuilding.header("Content-Type", "application/json"); | 			requestBuilding = requestBuilding.header("Content-Type", "application/json"); | ||||||
| 		final HttpRequest request = requestBuilding.PUT(BodyPublishers.ofString(body)).build(); | 		} | ||||||
|  | 		final HttpRequest request = requestBuilding.method(model, BodyPublishers.ofString(body)).build(); | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | 			try { | ||||||
| 			throw out; | 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | ||||||
|  | 				throw new RESTErrorResponseExeption(out.uuid, out.time, out.error, out.message, out.status, out.statusMessage); | ||||||
|  | 			} catch (final MismatchedInputException ex) { | ||||||
|  | 				throw new IOException("Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
|  | 			} catch (final JsonParseException ex) { | ||||||
|  | 				ex.printStackTrace(); | ||||||
|  | 				LOGGER.error("body: {}", httpResponse.body()); | ||||||
|  | 				throw new IOException("Fail to get the ERROR data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		if (clazz.equals(String.class)) { | 		if (clazz.equals(String.class)) { | ||||||
| 			return (T) httpResponse.body(); | 			return (T) httpResponse.body(); | ||||||
| 		} | 		} | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); | 		return this.mapper.readValue(httpResponse.body(), clazz); | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public <T, U> T delete(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | 	protected <T> T modelSendMap(final String model, final Class<T> clazz, final String urlOffset, final Map<String, Object> data) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
| 		final ObjectMapper mapper = new ObjectMapper(); |  | ||||||
| 		final HttpClient client = HttpClient.newHttpClient(); | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
| 		Builder requestBuilding = HttpRequest.newBuilder().uri(URI.create(this.baseUrl + urlOffset)); | 		String body = null; | ||||||
|  | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1).uri(URI.create(this.baseUrl + urlOffset)); | ||||||
| 		if (this.token != null) { | 		if (this.token != null) { | ||||||
| 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Yota " + this.token); | 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | ||||||
|  | 		} | ||||||
|  | 		if (data == null) { | ||||||
|  | 			body = ""; | ||||||
|  | 		} else { | ||||||
|  | 			body = this.mapper.writeValueAsString(data); | ||||||
|  | 			requestBuilding = requestBuilding.header("Content-Type", "application/json"); | ||||||
|  | 		} | ||||||
|  | 		final HttpRequest request = requestBuilding.method(model, BodyPublishers.ofString(body)).build(); | ||||||
|  | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
|  | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
|  | 			try { | ||||||
|  | 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | ||||||
|  | 				throw new RESTErrorResponseExeption(out.uuid, out.time, out.error, out.message, out.status, out.statusMessage); | ||||||
|  | 			} catch (final MismatchedInputException ex) { | ||||||
|  | 				throw new IOException("Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (clazz.equals(String.class)) { | ||||||
|  | 			return (T) httpResponse.body(); | ||||||
|  | 		} | ||||||
|  | 		return this.mapper.readValue(httpResponse.body(), clazz); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public <T, U> void delete(final Class<T> clazz, final String urlOffset) throws RESTErrorResponseExeption, IOException, InterruptedException { | ||||||
|  | 		final HttpClient client = HttpClient.newHttpClient(); | ||||||
|  | 		Builder requestBuilding = HttpRequest.newBuilder().version(Version.HTTP_1_1).uri(URI.create(this.baseUrl + urlOffset)); | ||||||
|  | 		if (this.token != null) { | ||||||
|  | 			requestBuilding = requestBuilding.header(HttpHeaders.AUTHORIZATION, "Bearer " + this.token); | ||||||
| 		} | 		} | ||||||
| 		final HttpRequest request = requestBuilding.DELETE().build(); | 		final HttpRequest request = requestBuilding.DELETE().build(); | ||||||
| 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | 		final HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); | ||||||
| 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | 		if (httpResponse.statusCode() < 200 || httpResponse.statusCode() >= 300) { | ||||||
| 			final RESTErrorResponseExeption out = mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | 			try { | ||||||
| 			throw out; | 				final RESTErrorResponseExeption out = this.mapper.readValue(httpResponse.body(), RESTErrorResponseExeption.class); | ||||||
|  | 				throw new RESTErrorResponseExeption(out.uuid, out.time, out.error, out.message, out.status, out.statusMessage); | ||||||
|  | 			} catch (final MismatchedInputException ex) { | ||||||
|  | 				throw new IOException("Fail to get the data [" + httpResponse.statusCode() + "] " + httpResponse.body()); | ||||||
| 			} | 			} | ||||||
| 		if (clazz.equals(String.class)) { |  | ||||||
| 			return (T) httpResponse.body(); |  | ||||||
| 		} | 		} | ||||||
| 		final T out = mapper.readValue(httpResponse.body(), clazz); |  | ||||||
| 		return out; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ public class TestJson { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(SerializeAsJson.class); | 		final List<String> sqlCommand = DataFactory.createTable(SerializeAsJson.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
							
								
								
									
										99
									
								
								test/src/test/kar/archidata/TestListJson.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								test/src/test/kar/archidata/TestListJson.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | package test.kar.archidata; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.AfterAll; | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.BeforeAll; | ||||||
|  | import org.junit.jupiter.api.MethodOrderer; | ||||||
|  | import org.junit.jupiter.api.Order; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.api.TestMethodOrder; | ||||||
|  | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
|  | import org.kar.archidata.GlobalConfiguration; | ||||||
|  | import org.kar.archidata.dataAccess.DataAccess; | ||||||
|  | import org.kar.archidata.dataAccess.DataFactory; | ||||||
|  | import org.kar.archidata.db.DBEntry; | ||||||
|  | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.model.SerializeListAsJson; | ||||||
|  |  | ||||||
|  | @ExtendWith(StepwiseExtension.class) | ||||||
|  | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||||
|  | public class TestListJson { | ||||||
|  | 	final static private Logger LOGGER = LoggerFactory.getLogger(TestListJson.class); | ||||||
|  | 	 | ||||||
|  | 	@BeforeAll | ||||||
|  | 	public static void configureWebServer() throws Exception { | ||||||
|  | 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.dbHost = "memory"; | ||||||
|  | 			// for test we need to connect all time the DB | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} | ||||||
|  | 		// Connect the dataBase... | ||||||
|  | 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); | ||||||
|  | 		entry.connect(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@AfterAll | ||||||
|  | 	public static void removeDataBase() throws IOException { | ||||||
|  | 		LOGGER.info("Remove the test db"); | ||||||
|  | 		DBEntry.closeAllForceMode(); | ||||||
|  | 		ConfigBaseVariable.clearAllValue(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@Order(1) | ||||||
|  | 	@Test | ||||||
|  | 	public void testTableInsertAndRetrieve() throws Exception { | ||||||
|  | 		final List<String> sqlCommand = DataFactory.createTable(SerializeListAsJson.class); | ||||||
|  | 		for (final String elem : sqlCommand) { | ||||||
|  | 			LOGGER.debug("request: '{}'", elem); | ||||||
|  | 			DataAccess.executeSimpleQuerry(elem); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@Order(2) | ||||||
|  | 	@Test | ||||||
|  | 	public void testIO() throws Exception { | ||||||
|  | 		final SerializeListAsJson test = new SerializeListAsJson(); | ||||||
|  | 		test.data = new ArrayList<>(); | ||||||
|  | 		test.data.add(5); | ||||||
|  | 		test.data.add(2); | ||||||
|  | 		test.data.add(8); | ||||||
|  | 		test.data.add(6); | ||||||
|  | 		test.data.add(51); | ||||||
|  | 		 | ||||||
|  | 		final SerializeListAsJson insertedData = DataAccess.insert(test); | ||||||
|  | 		 | ||||||
|  | 		Assertions.assertNotNull(insertedData); | ||||||
|  | 		Assertions.assertNotNull(insertedData.id); | ||||||
|  | 		Assertions.assertTrue(insertedData.id >= 0); | ||||||
|  | 		Assertions.assertNotNull(insertedData.data); | ||||||
|  | 		Assertions.assertEquals(5, insertedData.data.size()); | ||||||
|  | 		Assertions.assertEquals(test.data.get(0), insertedData.data.get(0)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(1), insertedData.data.get(1)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(2), insertedData.data.get(2)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(3), insertedData.data.get(3)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(4), insertedData.data.get(4)); | ||||||
|  | 		 | ||||||
|  | 		// Try to retrieve all the data: | ||||||
|  | 		final SerializeListAsJson retrieve = DataAccess.get(SerializeListAsJson.class, insertedData.id); | ||||||
|  | 		 | ||||||
|  | 		Assertions.assertNotNull(retrieve); | ||||||
|  | 		Assertions.assertNotNull(retrieve.id); | ||||||
|  | 		Assertions.assertTrue(retrieve.id >= 0); | ||||||
|  | 		Assertions.assertNotNull(retrieve.data); | ||||||
|  | 		Assertions.assertEquals(5, retrieve.data.size()); | ||||||
|  | 		Assertions.assertEquals(test.data.get(0), retrieve.data.get(0)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(1), retrieve.data.get(1)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(2), retrieve.data.get(2)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(3), retrieve.data.get(3)); | ||||||
|  | 		Assertions.assertEquals(test.data.get(4), retrieve.data.get(4)); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
| @@ -57,7 +57,7 @@ public class TestManyToMany { | |||||||
| 		sqlCommand.addAll(sqlCommand2); | 		sqlCommand.addAll(sqlCommand2); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ public class TestManyToOne { | |||||||
| 		sqlCommand.addAll(sqlCommand2); | 		sqlCommand.addAll(sqlCommand2); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ public class TestOneToMany { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(TypesTable.class); | 		final List<String> sqlCommand = DataFactory.createTable(TypesTable.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
							
								
								
									
										121
									
								
								test/src/test/kar/archidata/TestRawQuery.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								test/src/test/kar/archidata/TestRawQuery.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | package test.kar.archidata; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.AfterAll; | ||||||
|  | import org.junit.jupiter.api.Assertions; | ||||||
|  | import org.junit.jupiter.api.BeforeAll; | ||||||
|  | import org.junit.jupiter.api.MethodOrderer; | ||||||
|  | import org.junit.jupiter.api.Order; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.api.TestMethodOrder; | ||||||
|  | import org.junit.jupiter.api.extension.ExtendWith; | ||||||
|  | import org.kar.archidata.GlobalConfiguration; | ||||||
|  | import org.kar.archidata.dataAccess.DataAccess; | ||||||
|  | import org.kar.archidata.dataAccess.DataFactory; | ||||||
|  | import org.kar.archidata.db.DBEntry; | ||||||
|  | import org.kar.archidata.tools.ConfigBaseVariable; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
|  | import test.kar.archidata.model.TypesTable; | ||||||
|  |  | ||||||
|  | @ExtendWith(StepwiseExtension.class) | ||||||
|  | @TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||||||
|  | public class TestRawQuery { | ||||||
|  | 	final static private Logger LOGGER = LoggerFactory.getLogger(TestTypes.class); | ||||||
|  | 	 | ||||||
|  | 	@BeforeAll | ||||||
|  | 	public static void configureWebServer() throws Exception { | ||||||
|  | 		if (!"true".equalsIgnoreCase(System.getenv("TEST_E2E_MODE"))) { | ||||||
|  | 			ConfigBaseVariable.dbType = "sqlite"; | ||||||
|  | 			ConfigBaseVariable.dbHost = "memory"; | ||||||
|  | 			// for test we need to connect all time the DB | ||||||
|  | 			ConfigBaseVariable.dbKeepConnected = "true"; | ||||||
|  | 		} | ||||||
|  | 		// Connect the dataBase... | ||||||
|  | 		final DBEntry entry = DBEntry.createInterface(GlobalConfiguration.dbConfig); | ||||||
|  | 		entry.connect(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@AfterAll | ||||||
|  | 	public static void removeDataBase() throws IOException { | ||||||
|  | 		LOGGER.info("Remove the test db"); | ||||||
|  | 		DBEntry.closeAllForceMode(); | ||||||
|  | 		ConfigBaseVariable.clearAllValue(); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@Order(1) | ||||||
|  | 	@Test | ||||||
|  | 	public void testCreateTable() throws Exception { | ||||||
|  | 		final List<String> sqlCommand = DataFactory.createTable(TypesTable.class); | ||||||
|  | 		for (final String elem : sqlCommand) { | ||||||
|  | 			LOGGER.debug("request: '{}'", elem); | ||||||
|  | 			DataAccess.executeSimpleQuerry(elem); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	@Order(2) | ||||||
|  | 	@Test | ||||||
|  | 	public void testGet() throws Exception { | ||||||
|  | 		 | ||||||
|  | 		final TypesTable test = new TypesTable(); | ||||||
|  | 		test.intData = 95; | ||||||
|  | 		test.floatData = 1.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 96; | ||||||
|  | 		test.floatData = 2.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 97; | ||||||
|  | 		test.floatData = 3.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 98; | ||||||
|  | 		test.floatData = 4.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 99; | ||||||
|  | 		test.floatData = 5.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 99; | ||||||
|  | 		test.floatData = 6.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		test.intData = 99; | ||||||
|  | 		test.floatData = 7.0F; | ||||||
|  | 		DataAccess.insert(test); | ||||||
|  | 		{ | ||||||
|  | 			String querry = """ | ||||||
|  | 					SELECT * | ||||||
|  | 					FROM TypesTable | ||||||
|  | 					WHERE `intData` = ? | ||||||
|  | 					ORDER BY id DESC | ||||||
|  | 					"""; | ||||||
|  | 			List<Object> parameters = List.of(Integer.valueOf(99)); | ||||||
|  | 			// Try to retrieve all the data: | ||||||
|  | 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, querry, parameters); | ||||||
|  | 			 | ||||||
|  | 			Assertions.assertNotNull(retrieve); | ||||||
|  | 			Assertions.assertEquals(3, retrieve.size()); | ||||||
|  | 			Assertions.assertEquals(99, retrieve.get(0).intData); | ||||||
|  | 			Assertions.assertEquals(7.0F, retrieve.get(0).floatData); | ||||||
|  | 			Assertions.assertEquals(6.0F, retrieve.get(1).floatData); | ||||||
|  | 			Assertions.assertEquals(5.0F, retrieve.get(2).floatData); | ||||||
|  | 		} | ||||||
|  | 		{ | ||||||
|  | 			 | ||||||
|  | 			String querry = """ | ||||||
|  | 					SELECT DISTINCT intData | ||||||
|  | 					FROM TypesTable | ||||||
|  | 					WHERE `intData` = ? | ||||||
|  | 					ORDER BY id DESC | ||||||
|  | 					"""; | ||||||
|  | 			List<Object> parameters = List.of(Integer.valueOf(99)); | ||||||
|  | 			// Try to retrieve all the data: | ||||||
|  | 			final List<TypesTable> retrieve = DataAccess.query(TypesTable.class, querry, parameters); | ||||||
|  | 			 | ||||||
|  | 			Assertions.assertNotNull(retrieve); | ||||||
|  | 			Assertions.assertEquals(1, retrieve.size()); | ||||||
|  | 			Assertions.assertEquals(99, retrieve.get(0).intData); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | } | ||||||
| @@ -65,7 +65,7 @@ public class TestSimpleTable { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(SimpleTable.class); | 		final List<String> sqlCommand = DataFactory.createTable(SimpleTable.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 		final SimpleTable test = new SimpleTable(); | 		final SimpleTable test = new SimpleTable(); | ||||||
| 		test.data = TestSimpleTable.DATA_INJECTED; | 		test.data = TestSimpleTable.DATA_INJECTED; | ||||||
| @@ -91,7 +91,7 @@ public class TestSimpleTable { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void testReadAllValuesUnreadable() throws Exception { | 	public void testReadAllValuesUnreadable() throws Exception { | ||||||
| 		// check the full values | 		// check the full values | ||||||
| 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, new QueryOptions(QueryOptions.READ_ALL_COLOMN)); | 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, QueryOptions.READ_ALL_COLOMN); | ||||||
| 		 | 		 | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| @@ -114,7 +114,7 @@ public class TestSimpleTable { | |||||||
| 		final SimpleTable test = new SimpleTable(); | 		final SimpleTable test = new SimpleTable(); | ||||||
| 		test.data = TestSimpleTable.DATA_INJECTED_2; | 		test.data = TestSimpleTable.DATA_INJECTED_2; | ||||||
| 		DataAccess.update(test, TestSimpleTable.idOfTheObject, List.of("data")); | 		DataAccess.update(test, TestSimpleTable.idOfTheObject, List.of("data")); | ||||||
| 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, new QueryOptions(QueryOptions.READ_ALL_COLOMN)); | 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, QueryOptions.READ_ALL_COLOMN); | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| 		Assertions.assertEquals(TestSimpleTable.idOfTheObject, retrieve.id); | 		Assertions.assertEquals(TestSimpleTable.idOfTheObject, retrieve.id); | ||||||
| @@ -139,7 +139,7 @@ public class TestSimpleTable { | |||||||
| 	public void testReadDeletedObject() throws Exception { | 	public void testReadDeletedObject() throws Exception { | ||||||
| 		 | 		 | ||||||
| 		// check if we set get deleted element | 		// check if we set get deleted element | ||||||
| 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, new QueryOptions(QueryOptions.ACCESS_DELETED_ITEMS)); | 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, QueryOptions.ACCESS_DELETED_ITEMS); | ||||||
| 		Assertions.assertNull(retrieve); | 		Assertions.assertNull(retrieve); | ||||||
| 		 | 		 | ||||||
| 	} | 	} | ||||||
| @@ -148,7 +148,7 @@ public class TestSimpleTable { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void testReadAllValuesUnreadableOfDeletedObject() throws Exception { | 	public void testReadAllValuesUnreadableOfDeletedObject() throws Exception { | ||||||
| 		// check if we set get deleted element with all data | 		// check if we set get deleted element with all data | ||||||
| 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, new QueryOptions(QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN)); | 		final SimpleTable retrieve = DataAccess.get(SimpleTable.class, TestSimpleTable.idOfTheObject, QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN); | ||||||
| 		Assertions.assertNull(retrieve); | 		Assertions.assertNull(retrieve); | ||||||
| 		 | 		 | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ public class TestSimpleTableSoftDelete { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(SimpleTableSoftDelete.class); | 		final List<String> sqlCommand = DataFactory.createTable(SimpleTableSoftDelete.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 		final SimpleTableSoftDelete test = new SimpleTableSoftDelete(); | 		final SimpleTableSoftDelete test = new SimpleTableSoftDelete(); | ||||||
| 		test.data = TestSimpleTableSoftDelete.DATA_INJECTED; | 		test.data = TestSimpleTableSoftDelete.DATA_INJECTED; | ||||||
| @@ -92,7 +92,7 @@ public class TestSimpleTableSoftDelete { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void testReadAllValuesUnreadable() throws Exception { | 	public void testReadAllValuesUnreadable() throws Exception { | ||||||
| 		// check the full values | 		// check the full values | ||||||
| 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, new QueryOptions(QueryOptions.READ_ALL_COLOMN)); | 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, QueryOptions.READ_ALL_COLOMN); | ||||||
| 		 | 		 | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| @@ -118,8 +118,7 @@ public class TestSimpleTableSoftDelete { | |||||||
| 		final SimpleTableSoftDelete test = new SimpleTableSoftDelete(); | 		final SimpleTableSoftDelete test = new SimpleTableSoftDelete(); | ||||||
| 		test.data = TestSimpleTableSoftDelete.DATA_INJECTED_2; | 		test.data = TestSimpleTableSoftDelete.DATA_INJECTED_2; | ||||||
| 		DataAccess.update(test, TestSimpleTableSoftDelete.idOfTheObject, List.of("data")); | 		DataAccess.update(test, TestSimpleTableSoftDelete.idOfTheObject, List.of("data")); | ||||||
| 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, | 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN); | ||||||
| 				new QueryOptions(QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN)); |  | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | ||||||
| @@ -151,7 +150,7 @@ public class TestSimpleTableSoftDelete { | |||||||
| 	public void testReadDeletedObject() throws Exception { | 	public void testReadDeletedObject() throws Exception { | ||||||
| 		 | 		 | ||||||
| 		// check if we set get deleted element | 		// check if we set get deleted element | ||||||
| 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, new QueryOptions(QueryOptions.ACCESS_DELETED_ITEMS)); | 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, QueryOptions.ACCESS_DELETED_ITEMS); | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | ||||||
| @@ -166,8 +165,7 @@ public class TestSimpleTableSoftDelete { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void testReadAllValuesUnreadableOfDeletedObject() throws Exception { | 	public void testReadAllValuesUnreadableOfDeletedObject() throws Exception { | ||||||
| 		// check if we set get deleted element with all data | 		// check if we set get deleted element with all data | ||||||
| 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, | 		final SimpleTableSoftDelete retrieve = DataAccess.get(SimpleTableSoftDelete.class, TestSimpleTableSoftDelete.idOfTheObject, QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN); | ||||||
| 				new QueryOptions(QueryOptions.ACCESS_DELETED_ITEMS, QueryOptions.READ_ALL_COLOMN)); |  | ||||||
| 		Assertions.assertNotNull(retrieve); | 		Assertions.assertNotNull(retrieve); | ||||||
| 		Assertions.assertNotNull(retrieve.id); | 		Assertions.assertNotNull(retrieve.id); | ||||||
| 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | 		Assertions.assertEquals(TestSimpleTableSoftDelete.idOfTheObject, retrieve.id); | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ public class TestTypeEnum1 { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(TypesEnum1.class); | 		final List<String> sqlCommand = DataFactory.createTable(TypesEnum1.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ public class TestTypeEnum2 { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(TypesEnum2.class); | 		final List<String> sqlCommand = DataFactory.createTable(TypesEnum2.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ public class TestTypes { | |||||||
| 		final List<String> sqlCommand = DataFactory.createTable(TypesTable.class); | 		final List<String> sqlCommand = DataFactory.createTable(TypesTable.class); | ||||||
| 		for (final String elem : sqlCommand) { | 		for (final String elem : sqlCommand) { | ||||||
| 			LOGGER.debug("request: '{}'", elem); | 			LOGGER.debug("request: '{}'", elem); | ||||||
| 			DataAccess.executeSimpleQuerry(elem, false); | 			DataAccess.executeSimpleQuerry(elem); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| @@ -449,7 +449,7 @@ public class TestTypes { | |||||||
| 					"varcharData": null | 					"varcharData": null | ||||||
| 				} | 				} | ||||||
| 				"""; | 				"""; | ||||||
| 		final int nbUpdate = DataAccess.updateWithJson(TypesTable.class, insertedData.id, jsonData); | 		final int nbUpdate = DataAccess.updateWithJson(TypesTable.class, insertedData.id, jsonData, null); | ||||||
| 		Assertions.assertEquals(1, nbUpdate); | 		Assertions.assertEquals(1, nbUpdate); | ||||||
| 		 | 		 | ||||||
| 		// Get new data | 		// Get new data | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								test/src/test/kar/archidata/model/SerializeListAsJson.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/src/test/kar/archidata/model/SerializeListAsJson.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | package test.kar.archidata.model; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import org.kar.archidata.annotation.DataJson; | ||||||
|  | import org.kar.archidata.model.GenericData; | ||||||
|  |  | ||||||
|  | public class SerializeListAsJson extends GenericData { | ||||||
|  |  | ||||||
|  | 	@DataJson | ||||||
|  | 	public List<Integer> data; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -18,10 +18,10 @@ function __run() #(step, name, cmd) | |||||||
|     if [[ 0 == $exitcode ]]; then |     if [[ 0 == $exitcode ]]; then | ||||||
|         echo -e "${C_GREEN}OK!${C_RESET}" |         echo -e "${C_GREEN}OK!${C_RESET}" | ||||||
|     else |     else | ||||||
|         echo -e "${C_RED}NOK! (${exitcode})${C_RESET}\n\n$output" |         echo -e "${C_RED}ERROR! (${exitcode})${C_RESET}\n\n$output" | ||||||
|         exit 1 |         exit 1 | ||||||
|     fi |     fi | ||||||
| } | } | ||||||
|  |  | ||||||
| __run "1/1" "Check JAVA code format" "mvn formatter:verify" | __run "1/1" "Check JAVA code format" "mvn formatter:validate" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 0.5.0 | 0.6.2 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user