Compare commits

...

80 Commits

Author SHA1 Message Date
Edouard DUPIN
ec762cfb96 [RELEASE] Release v0.29.0 2025-04-22 14:14:54 +02:00
Edouard DUPIN
31d353de40 [FEAT] update personal email 2025-04-22 12:29:26 +02:00
21d7eace4c [FIX] cover upload API 2025-04-22 12:27:24 +02:00
b530cb629b [FEAT] add capability to use @ManyToManyLocal that is an implementation compatible with NoSql MAny-ToMany link
This feature manage to update the 2 side of the local stored of the data
2025-04-22 11:30:58 +02:00
0cf718d415 [FIX] throw in @ManyToMany when not a list instead of log a simple error 2025-04-22 11:29:04 +02:00
963f53c2ad [FEAT] add capability to load previous data befor call updaete od soem fields 2025-04-22 11:27:42 +02:00
7f5987338a [FEAT] update naming of the TableCoversGeneric to be generic 2025-04-22 11:24:19 +02:00
70a9be86b2 [FIX] timestamp check for Github test 2025-04-22 11:23:04 +02:00
11b49ea95d [FIX] the code generation does not manage corectly the field name 2025-04-19 18:55:16 +02:00
18329659c8 [FEAT] update path structure of the project 2025-04-19 17:35:42 +02:00
74278041d6 [VERSION] update dev tag version 2025-04-18 08:31:53 +02:00
d45e07450f [RELEASE] Release v0.28.4 2025-04-18 08:31:50 +02:00
8c46d9b441 [FIX] Error 403 instead of 401 when no role found in token. 2025-04-18 08:31:17 +02:00
106e64a90c [FIX] @ManyToMany auto link generation
Not functionnal di to the bijectivity model ==> need fix it
2025-04-18 08:14:36 +02:00
8a9567d730 [VERSION] update dev tag version 2025-04-15 20:37:23 +02:00
edfbc5da21 [RELEASE] Release v0.28.2 2025-04-15 20:37:20 +02:00
95a37fc7de [FIX] order the inputs in typescript generation 2025-04-15 20:36:10 +02:00
2ba7d47b10 [VERSION] update dev tag version 2025-04-14 13:43:46 +02:00
2a2599f35c [RELEASE] Release v0.28.0 2025-04-14 13:43:42 +02:00
3fba44a041 [FIX] build 2025-04-14 13:33:34 +02:00
dependabot[bot]
6d10f564eb [DEV-OPS] (dependabot) Bump org.apache.maven.plugins:maven-gpg-plugin
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.2.7.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.2.7)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-version: 3.2.7
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 12:51:32 +02:00
dependabot[bot]
d608e534c3 [DEV-OPS] (dependabot) Bump dev.morphia.morphia:morphia-core
Bumps [dev.morphia.morphia:morphia-core](https://github.com/MorphiaOrg/morphia) from 2.4.15 to 2.4.16.
- [Release notes](https://github.com/MorphiaOrg/morphia/releases)
- [Changelog](https://github.com/MorphiaOrg/morphia/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MorphiaOrg/morphia/compare/v2.4.15...v2.4.16)

---
updated-dependencies:
- dependency-name: dev.morphia.morphia:morphia-core
  dependency-version: 2.4.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 12:51:27 +02:00
dependabot[bot]
5a03f338c4 [DEV-OPS] (dependabot) Bump net.revelc.code.formatter:formatter-maven-plugin
Bumps net.revelc.code.formatter:formatter-maven-plugin from 2.24.1 to 2.26.0.

---
updated-dependencies:
- dependency-name: net.revelc.code.formatter:formatter-maven-plugin
  dependency-version: 2.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 12:50:39 +02:00
dependabot[bot]
bf5a0e5ed0
[DEV-OPS] (dependabot) Bump com.nimbusds:nimbus-jose-jwt
Bumps [com.nimbusds:nimbus-jose-jwt](https://bitbucket.org/connect2id/nimbus-jose-jwt) from 10.0.2 to 10.2.
- [Changelog](https://bitbucket.org/connect2id/nimbus-jose-jwt/src/master/CHANGELOG.txt)
- [Commits](https://bitbucket.org/connect2id/nimbus-jose-jwt/branches/compare/10.2..10.0.2)

---
updated-dependencies:
- dependency-name: com.nimbusds:nimbus-jose-jwt
  dependency-version: '10.2'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 10:32:00 +00:00
32d7be23e9 [FEAT] update @ManyToMany Tests 2025-04-13 15:50:25 +02:00
7a7ca29081 [FIX] update of the @ManyToMany values 2025-04-13 15:49:58 +02:00
464f844eed [FEAT,API] review the manyToMany link table name to support better automatic models
- change link table name
  - nupport reverse add link, support table name with max size of 64 with hash reduce
2025-04-11 01:42:11 +02:00
401bd8318a [FEAT] add capability to select the frmat of thumbnail generate 2025-04-09 12:52:19 +02:00
05a51ad87a [FEAT] move in the correct domain org.kar -> org.atriasoft 2025-04-08 21:09:38 +02:00
6298d09828 [VERSION] update dev tag version 2025-04-08 20:41:48 +02:00
aa8330fa1a [RELEASE] Release v0.27.0 2025-04-08 20:41:45 +02:00
37629b4cb2 [FIX] doc generation 2025-04-08 20:41:00 +02:00
69f69a8113 [FIX] Double and double inclution generate a double inclusion in Typescript generation 2025-04-08 10:27:30 +02:00
dependabot[bot]
7185a34fda
[DEV-OPS] (dependabot) Bump advanced-security/maven-dependency-submission-action from 4.1.1 to 4.1.2 (#42)
Bumps
[advanced-security/maven-dependency-submission-action](https://github.com/advanced-security/maven-dependency-submission-action)
from 4.1.1 to 4.1.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/advanced-security/maven-dependency-submission-action/releases">advanced-security/maven-dependency-submission-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Add cycle safety for transitive dependencies by <a
href="https://github.com/juxtin"><code>@​juxtin</code></a> in <a
href="https://redirect.github.com/advanced-security/maven-dependency-submission-action/pull/103">advanced-security/maven-dependency-submission-action#103</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/juxtin"><code>@​juxtin</code></a> made
their first contribution in <a
href="https://redirect.github.com/advanced-security/maven-dependency-submission-action/pull/103">advanced-security/maven-dependency-submission-action#103</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/advanced-security/maven-dependency-submission-action/compare/v4...v4.1.2">https://github.com/advanced-security/maven-dependency-submission-action/compare/v4...v4.1.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="aeab9f8852"><code>aeab9f8</code></a>
Merge pull request <a
href="https://redirect.github.com/advanced-security/maven-dependency-submission-action/issues/106">#106</a>
from advanced-security/juxtin/prep-412</li>
<li><a
href="bc43a53a41"><code>bc43a53</code></a>
Update step numbers</li>
<li><a
href="8ec6a0b12e"><code>8ec6a0b</code></a>
Add note about running npm build</li>
<li><a
href="8c8c37cf51"><code>8c8c37c</code></a>
Merge branch 'main' into juxtin/prep-412</li>
<li><a
href="4ccf7bf0a3"><code>4ccf7bf</code></a>
Update version to 4.1.2 and update release instructions</li>
<li><a
href="973a8cf442"><code>973a8cf</code></a>
Merge pull request <a
href="https://redirect.github.com/advanced-security/maven-dependency-submission-action/issues/104">#104</a>
from advanced-security/juxtin/prep-412</li>
<li><a
href="48f232b0d1"><code>48f232b</code></a>
Update dist files</li>
<li><a
href="769e1e8558"><code>769e1e8</code></a>
Prepare for 4.1.2 release</li>
<li><a
href="298a804769"><code>298a804</code></a>
Upgrade version of Maven plugin</li>
<li><a
href="29fd39885e"><code>29fd398</code></a>
Merge pull request <a
href="https://redirect.github.com/advanced-security/maven-dependency-submission-action/issues/103">#103</a>
from advanced-security/juxtin/handle-cycles</li>
<li>Additional commits viewable in <a
href="4f64ddab9d...aeab9f8852">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=advanced-security/maven-dependency-submission-action&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 09:06:16 +02:00
b12108ec00 [FIX] test on DateTime is ended and solution in 90% operational 2025-04-07 23:08:23 +02:00
ecc8829e8c [FEAT] develop a new RESTApi interface to be easiest and flexible 2025-04-06 23:26:46 +02:00
e7e8c48c5c [FEAT] add OffsetDateTime in the BDD interface with UTC force 2025-04-06 23:26:19 +02:00
c09c29bf8d [FEAT] add jakarta some methode to parse the date more flexible 2025-04-06 23:25:48 +02:00
16bb30b260 [FEAT] add some test for time system 2025-04-06 23:24:58 +02:00
f044473a67 [FEAT] Jackson update date serializer to be more permissive 2025-04-06 23:24:12 +02:00
1d375f8580 [VERSION] update dev tag version 2025-04-03 10:30:43 +02:00
e2d35c5060 [RELEASE] Release v0.26.4 2025-04-03 10:30:40 +02:00
9ebd37788d [FIX] ready to deploy on maven central 2025-04-03 10:29:56 +02:00
8dde49adff [FIX] ApiNotNull inplementation 2025-04-03 10:25:33 +02:00
5960bbc666 [VERSION] update dev tag version 2025-04-02 23:50:03 +02:00
afcbb4711c [RELEASE] Release v0.26.2 2025-04-02 23:50:00 +02:00
a0b22e00bd [FEAT] update for maven central 2025-04-02 23:49:28 +02:00
a49e374bd1 [DEV] remove unneeded libraries 2025-04-02 22:28:23 +02:00
2b43d348a8 [VERSION] update dev tag version 2025-04-02 21:46:56 +02:00
242e6b9261 [RELEASE] Release v0.26.0 2025-04-02 21:46:53 +02:00
c627484b49 [FIX] annotation in the common model 2025-04-02 21:42:17 +02:00
44df939873 [FEAT] add ApiNotNull to overwrite all fields possibility 2025-04-02 21:34:27 +02:00
b283f8545c [FEAT] add readable optionnal for field 2025-04-02 21:33:52 +02:00
dependabot[bot]
6e4c10724a [DEV-OPS] (dependabot) Bump org.apache.maven.plugins:maven-surefire-plugin
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.2...surefire-3.5.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 19:39:12 +02:00
41aa78667f [FIX] some basic types generation constraint 2025-04-01 22:18:58 +02:00
f7ba570913 [FIX] foreinKeyValidator 2025-04-01 22:18:50 +02:00
55957278a0 [VERSION] update dev tag version 2025-03-30 23:28:36 +02:00
a15be78e10 [RELEASE] Release v0.25.6 2025-03-30 23:27:32 +02:00
abff1ada45 [FIX] (RestApi tool) null object are serialize as null (like browser) 2025-03-30 23:24:17 +02:00
1c769827cf [FIX] (RestApi tool) multipart file is not merged with nest parameter 2025-03-30 23:23:51 +02:00
e09de7cc7a [FEAT] remove dataJson plugin that never exist in NoSQL 2025-03-30 17:00:19 +02:00
a5b9b60294 [FEAT] rename parameter to be clear 2025-03-30 16:59:34 +02:00
288e1f8293 [FEAT] add capabilituy of rest API to manage multipart 2025-03-30 16:58:34 +02:00
d9a5f1ece2 [FEAT] configure deleted element to be missing or false in morphia 2025-03-29 20:23:42 +01:00
f77c6ce13e [FEAT] remove doucle of code 2025-03-29 20:23:04 +01:00
85754f20f8 [FIX] configuration of mongo interface 2025-03-29 20:22:44 +01:00
969bf78576 [FEAT] configure back compatibility with mongo 2025-03-29 20:21:07 +01:00
f0cf1acf8a [FIX] configure morphia that is compatible with mongo 2025-03-29 20:20:21 +01:00
7208db5bdf [FEAT] normalize Mongo and SQL 2025-03-29 20:19:55 +01:00
5b88401d48 [FIX] name of the primary key of the cover is not managed 2025-03-28 21:13:15 +01:00
d53a0719b5 [FEAT] fix 400 error in input error 2025-03-21 08:57:24 +01:00
3e7a1a5473 [VERSION] update dev tag version 2025-03-19 23:36:56 +01:00
c7338c7877 [RELEASE] Release v0.25.4 2025-03-19 23:35:39 +01:00
1007628713 [FEAT] update test 2025-03-19 23:34:24 +01:00
84a968a426 [Fix] correct @OneToMany on ObjectId 2025-03-19 19:15:24 +01:00
581c936bec [VERSION] update dev tag version 2025-03-18 23:07:41 +01:00
a6204032b5 [RELEASE] Release v0.25.2 2025-03-18 23:04:15 +01:00
e824feb8a2 [FIX] fix json serialize null in error (remove) 2025-03-18 15:27:42 +01:00
26ea70f80c [FIX] correct some generic code generation 2025-03-18 15:27:39 +01:00
6291466df0 [VERSION] update dev tag version 2025-03-17 21:59:02 +01:00
322 changed files with 7490 additions and 2708 deletions

View File

@ -1,30 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="test/src">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="test/resources">
<attributes>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
@ -35,5 +15,31 @@
<attribute name="optional" value="true"/> <attribute name="optional" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/testResources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src/main">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
java-version: '21' java-version: '21'
@ -32,4 +32,4 @@ jobs:
# Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
- name: Update dependency graph - name: Update dependency graph
uses: advanced-security/maven-dependency-submission-action@4f64ddab9d742a4806eeb588d238e4c311a8397d uses: advanced-security/maven-dependency-submission-action@aeab9f885293af501bae8bdfe88c589528ea5e25

132
pom.xml
View File

@ -1,25 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>kangaroo-and-rabbit</groupId> <groupId>org.atria-soft</groupId>
<artifactId>archidata</artifactId> <artifactId>archidata</artifactId>
<version>0.25.0</version> <version>0.29.0</version>
<repositories> <description>Wrapper to manage a simple interface for REST project to bind MySQL, SQLite or mongoDB.</description>
<repository> <url>https://github.com/kangaroo-and-rabbit/archidata</url>
<id>gitea</id> <licenses>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> <license>
</repository> <name>Mozilla Public License 2.0</name>
</repositories> <url>https://opensource.org/licenses/MPL-2.0</url>
<distributionManagement> <distribution>repo</distribution>
<repository> </license>
<id>gitea</id> </licenses>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> <developers>
</repository> <developer>
<snapshotRepository> <id>dev1</id>
<id>gitea</id> <name>Edouard DUPIN</name>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url> <email>edouard.dupin@proton.me</email>
</snapshotRepository> <roles>
</distributionManagement> <role>Lead Developer</role>
</roles>
</developer>
</developers>
<scm>
<url>https://github.com/kangaroo-and-rabbit/archidata</url>
<connection>scm:git:git://github.com/kangaroo-and-rabbit/archidata.git</connection>
<developerConnection>scm:git:ssh:github.com/kangaroo-and-rabbit/archidata.git</developerConnection>
</scm>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
@ -89,16 +97,6 @@
<groupId>org.glassfish.jersey.ext</groupId> <groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId> <artifactId>jersey-bean-validation</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>4.0.5</version>
</dependency>
<dependency> <dependency>
<groupId>org.glassfish.jaxb</groupId> <groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId> <artifactId>jaxb-runtime</artifactId>
@ -109,17 +107,6 @@
<artifactId>jakarta.ws.rs-api</artifactId> <artifactId>jakarta.ws.rs-api</artifactId>
<version>4.0.0</version> <version>4.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons-runtime</artifactId>
<version>4.2.0</version>
</dependency>
<!-- continu to be needed ??? -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope>
</dependency>
<!-- Serialize and un-serialize request in JSON--> <!-- Serialize and un-serialize request in JSON-->
<dependency> <dependency>
<groupId>org.glassfish.jersey.media</groupId> <groupId>org.glassfish.jersey.media</groupId>
@ -162,7 +149,7 @@
<dependency> <dependency>
<groupId>com.nimbusds</groupId> <groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId> <artifactId>nimbus-jose-jwt</artifactId>
<version>10.0.2</version> <version>10.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jakarta.persistence</groupId> <groupId>jakarta.persistence</groupId>
@ -186,13 +173,15 @@
<dependency> <dependency>
<groupId>dev.morphia.morphia</groupId> <groupId>dev.morphia.morphia</groupId>
<artifactId>morphia-core</artifactId> <artifactId>morphia-core</artifactId>
<version>2.4.15</version> <version>2.4.16</version>
</dependency> </dependency>
<!-- MongoDB Java Driver --> <!-- MongoDB Java Driver -->
<dependency> <dependency>
<groupId>org.mongodb</groupId> <groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId> <artifactId>mongodb-driver-sync</artifactId>
<version>5.4.0-alpha0</version> <!--<version>5.3.1</version>-->
<!--Morphia 2.4.x does not support version upper than 4.x-->
<version>4.11.5</version>
</dependency> </dependency>
<!-- Bean Validation (JSR 303 / 380) --> <!-- Bean Validation (JSR 303 / 380) -->
<dependency> <dependency>
@ -200,11 +189,6 @@
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
<version>9.0.0.CR1</version> <version>9.0.0.CR1</version>
</dependency> </dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- <!--
************************************************************ ************************************************************
** TEST dependency ** ** TEST dependency **
@ -225,7 +209,7 @@
<dependency> <dependency>
<groupId>net.revelc.code.formatter</groupId> <groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId> <artifactId>formatter-maven-plugin</artifactId>
<version>2.25.0</version> <version>2.26.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -234,16 +218,16 @@
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<sourceDirectory>src</sourceDirectory> <sourceDirectory>src/main</sourceDirectory>
<resources> <resources>
<resource> <resource>
<directory>${basedir}/src/resources</directory> <directory>${basedir}/src/resources</directory>
</resource> </resource>
</resources> </resources>
<testSourceDirectory>test/src</testSourceDirectory> <testSourceDirectory>src/test</testSourceDirectory>
<testResources> <testResources>
<testResource> <testResource>
<directory>${basedir}/test/resources</directory> <directory>${basedir}/src/testResources</directory>
</testResource> </testResource>
</testResources> </testResources>
<plugins> <plugins>
@ -265,7 +249,7 @@
<execution> <execution>
<id>attach-sources</id> <id>attach-sources</id>
<goals> <goals>
<goal>jar</goal> <goal>jar-no-fork</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
@ -288,7 +272,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version> <version>3.5.3</version>
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
@ -308,10 +292,14 @@
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.0</version> <version>3.3.0</version>
<configuration> <executions>
<show>private</show> <execution>
<nohelp>true</nohelp> <id>attach-javadocs</id>
</configuration> <goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin> </plugin>
<!-- Check the style of the code --> <!-- Check the style of the code -->
<plugin> <plugin>
@ -329,7 +317,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.24.1</version> <version>2.26.0</version>
<configuration> <configuration>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
<lineEnding>LF</lineEnding> <lineEnding>LF</lineEnding>
@ -370,19 +358,29 @@
--> -->
</configuration> </configuration>
</plugin> </plugin>
</plugins>
</build>
<!-- Generate Java-docs As Part Of Project Reports -->
<reporting>
<plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>3.3.0</version> <version>3.2.7</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.7.0</version>
<extensions>true</extensions>
<configuration> <configuration>
<show>public</show> <publishingServerId>central</publishingServerId>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</reporting> </build>
</project> </project>

311
pom.xml.versionsBackup Normal file
View File

@ -0,0 +1,311 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.6.1</version>
<properties>
<maven.compiler.version>3.1</maven.compiler.version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.dependency.version>3.1.1</maven.dependency.version>
<jersey.version>3.1.5</jersey.version>
<jaxb.version>2.3.1</jaxb.version>
<istack.version>4.1.1</istack.version>
</properties>
<repositories>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
</repository>
<snapshotRepository>
<id>gitea</id>
<url>https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/maven</url>
</snapshotRepository>
</distributionManagement>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.9</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-multipart -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>com.sun.istack</groupId>
<artifactId>istack-commons-runtime</artifactId>
<version>${istack.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<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>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0-M1</version>
<scope>provided</scope>
</dependency>
<!-- Interface for My-sql & sqlite DB -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.2.0</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.40.0.0</version>
</dependency>
<!-- Interface for JWT token -->
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.37.1</version>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.2.0-M1</version>
</dependency>
<!-- Swagger dependencies -->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-jakarta</artifactId>
<version>2.1.10</version>
</dependency>
<!--
************************************************************
** TEST dependency **
************************************************************
-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</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>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test/src</testSourceDirectory>
<testResources>
<testResource>
<directory>${basedir}/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<!--<encoding>${project.build.sourceEncoding}</encoding>-->
</configuration>
</plugin>
<!-- Create the source bundle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</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 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- Java-doc generation for stand-alone site -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
</configuration>
</plugin>
<!-- Check the style of the code -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>CheckStyle.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failOnViolation>true</failOnViolation>
<failsOnError>true</failsOnError>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
</configuration>
</plugin>
<plugin>
<groupId>net.revelc.code.formatter</groupId>
<artifactId>formatter-maven-plugin</artifactId>
<version>2.23.0</version>
<configuration>
<encoding>UTF-8</encoding>
<lineEnding>LF</lineEnding>
<configFile>Formatter.xml</configFile>
<directories>
<directory>src/</directory>
<directory>test/src</directory>
</directories>
<includes>
<include>**/*.java</include>
</includes>
<excludes>
<exclude>module-info.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- Generate Java-docs As Part Of Project Reports -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>public</show>
</configuration>
</plugin>
</plugins>
</reporting>
</project>

View File

@ -7,18 +7,18 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
import org.kar.archidata.GlobalConfiguration; import org.atriasoft.archidata.GlobalConfiguration;
import org.kar.archidata.UpdateJwtPublicKey; import org.atriasoft.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource; import org.atriasoft.archidata.api.DataResource;
import org.kar.archidata.catcher.ExceptionCatcher; import org.atriasoft.archidata.catcher.ExceptionCatcher;
import org.kar.archidata.catcher.FailExceptionCatcher; import org.atriasoft.archidata.catcher.FailExceptionCatcher;
import org.kar.archidata.catcher.InputExceptionCatcher; import org.atriasoft.archidata.catcher.InputExceptionCatcher;
import org.kar.archidata.catcher.SystemExceptionCatcher; import org.atriasoft.archidata.catcher.SystemExceptionCatcher;
import org.kar.archidata.db.DBConfig; import org.atriasoft.archidata.db.DBConfig;
import org.kar.archidata.filter.CORSFilter; import org.atriasoft.archidata.filter.CORSFilter;
import org.kar.archidata.filter.OptionFilter; import org.atriasoft.archidata.filter.OptionFilter;
import org.kar.archidata.migration.MigrationEngine; import org.atriasoft.archidata.migration.MigrationEngine;
import org.kar.archidata.tools.ConfigBaseVariable; import org.atriasoft.archidata.tools.ConfigBaseVariable;
import sample.archidata.basic.api.Front; import sample.archidata.basic.api.Front;
import sample.archidata.basic.api.HealthCheck; import sample.archidata.basic.api.HealthCheck;
import sample.archidata.basic.api.MediaResource; import sample.archidata.basic.api.MediaResource;

View File

@ -3,9 +3,9 @@ package sample.archidata.basic;
import java.util.List; import java.util.List;
import org.kar.archidata.api.DataResource; import org.atriasoft.archidata.api.DataResource;
import org.kar.archidata.dataAccess.DataFactoryTsApi; import org.atriasoft.archidata.dataAccess.DataFactoryTsApi;
import org.kar.archidata.tools.ConfigBaseVariable; import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -8,15 +8,15 @@ import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType; import org.atriasoft.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.TypeScriptProgress; import org.atriasoft.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.api.DataResource; import org.atriasoft.archidata.api.DataResource;
import org.kar.archidata.dataAccess.DataAccess; import org.atriasoft.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOn.AddOnDataJson; import org.atriasoft.archidata.dataAccess.addOn.AddOnDataJson;
import org.kar.archidata.exception.FailException; import org.atriasoft.archidata.exception.FailException;
import org.kar.archidata.exception.InputException; import org.atriasoft.archidata.exception.InputException;
import org.kar.archidata.model.Data; import org.atriasoft.archidata.model.Data;
import org.kar.archidata.tools.DataTools; import org.atriasoft.archidata.tools.DataTools;
import sample.archidata.basic.model.MyModel; import sample.archidata.basic.model.MyModel;
import sample.archidata.basic.model.Season; import sample.archidata.basic.model.Season;
import sample.archidata.basic.model.Series; import sample.archidata.basic.model.Series;

View File

@ -2,7 +2,7 @@ package sample.archidata.basic.migration;
import java.util.List; import java.util.List;
import org.kar.archidata.migration.MigrationSqlStep; import org.atriasoft.archidata.migration.MigrationSqlStep;
import sample.archidata.basic.model.MyModel; import sample.archidata.basic.model.MyModel;
public class Initialization extends MigrationSqlStep { public class Initialization extends MigrationSqlStep {

View File

@ -3,9 +3,9 @@ package sample.archidata.basic.model;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.kar.archidata.annotation.DataJson; import org.atriasoft.archidata.annotation.DataJson;
import org.kar.archidata.model.Data; import org.atriasoft.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete; import org.atriasoft.archidata.model.GenericDataSoftDelete;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;

View File

@ -1,7 +1,7 @@
package org.kar.archidata; package org.atriasoft.archidata;
import org.kar.archidata.tools.ConfigBaseVariable; import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.JWTWrapper; import org.atriasoft.archidata.tools.JWTWrapper;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -6,14 +6,14 @@ import java.lang.reflect.Parameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.kar.archidata.annotation.checker.Checker; import org.atriasoft.archidata.annotation.checker.Checker;
import org.kar.archidata.annotation.checker.CollectionItemNotNull; import org.atriasoft.archidata.annotation.checker.CollectionItemNotNull;
import org.kar.archidata.annotation.checker.CollectionItemUnique; import org.atriasoft.archidata.annotation.checker.CollectionItemUnique;
import org.kar.archidata.annotation.checker.CollectionNotEmpty; import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
import org.kar.archidata.dataAccess.QueryOptions; import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.options.OptionRenameColumn; import org.atriasoft.archidata.dataAccess.options.OptionRenameColumn;
import org.kar.archidata.dataAccess.options.OverrideTableName; import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.exception.DataAccessException; import org.atriasoft.archidata.exception.DataAccessException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -449,7 +449,7 @@ public class AnnotationTools {
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
continue; continue;
} }
if (AnnotationTools.getFieldNameRaw(field).equals(name)) { if (field.getName().equals(name)) {
return true; return true;
} }
} }

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -20,7 +20,7 @@ import java.lang.annotation.Target;
* - When a field is annotated with @DataNotRead, it will not be included in the * - When a field is annotated with @DataNotRead, it will not be included in the
* default data retrieval process from the database. * default data retrieval process from the database.
* - To override this behavior and read all columns, including those marked with * - To override this behavior and read all columns, including those marked with
* @DataNotRead, the query must include the option ReadAllColumn. * `@DataNotRead`, the query must include the option ReadAllColumn.
* *
* <p>Example: * <p>Example:
* <pre>{@code * <pre>{@code

View File

@ -0,0 +1,27 @@
package org.atriasoft.archidata.annotation;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* In NoSql entity the relation is stored in the 2 part of the entity,
* then it is needed to define the field that store the relation data value in the remote elements.
*/
@Retention(RUNTIME)
@Target({ FIELD, METHOD })
public @interface ManyToManyLocal {
/**
* The entity class that is the target of the
* association.
*/
Class<?> targetEntity();
/**
* The field that owns the revert value. empty if the relationship is unidirectional.
*/
String remoteField() default "";
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation; package org.atriasoft.archidata.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.addOn; package org.atriasoft.archidata.annotation.addOn;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.apiGenerator; package org.atriasoft.archidata.annotation.apiGenerator;
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -9,6 +9,11 @@ import java.lang.annotation.Target;
@Retention(RUNTIME) @Retention(RUNTIME)
@Target(FIELD) @Target(FIELD)
public @interface ApiAccessLimitation { public @interface ApiAccessLimitation {
/**
* (Optional) The field is accessible in read (GET)
*/
boolean readable() default true;
/** /**
* (Optional) The field is accessible in creation (POST) * (Optional) The field is accessible in creation (POST)
*/ */

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.apiGenerator; package org.atriasoft.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.apiGenerator; package org.atriasoft.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.apiGenerator; package org.atriasoft.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -22,7 +22,8 @@ import java.lang.annotation.Target;
* more flexible API designs where certain inputs can be omitted. * more flexible API designs where certain inputs can be omitted.
* *
* <p>Example: * <p>Example:
* <pre>{@code *
* {@code
* public class AlbumService { * public class AlbumService {
* *
* @POST * @POST
@ -39,7 +40,8 @@ import java.lang.annotation.Target;
* // some code * // some code
* } * }
* } * }
* }</pre> * }
*
* *
* Note: @FormDataParam must be allway at the last position. * Note: @FormDataParam must be allway at the last position.
* *
@ -47,7 +49,8 @@ import java.lang.annotation.Target;
* marked as optional, allowing the client to omit them when calling the API. * marked as optional, allowing the client to omit them when calling the API.
* *
* <p>Generated TypeScript code example: * <p>Generated TypeScript code example:
* <pre>{@code *
* {@code
* //Add a cover on a specific album * //Add a cover on a specific album
* export function uploadCover({ * export function uploadCover({
* restConfig, * restConfig,
@ -64,10 +67,11 @@ import java.lang.annotation.Target;
* uri?: string, // element is optional * uri?: string, // element is optional
* }, * },
* callbacks?: RESTCallbacks, * callbacks?: RESTCallbacks,
* }): Promise<Album> { ... * }): Promise<Album> { ... }
* }</pre> * }
* *
* The generated TypeScript function reflects the optional nature of the form data parameters. *
* The generated TypeScript function reflects the optional nature of the form data parameters
*/ */
@Target({ ElementType.PARAMETER }) @Target({ ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -0,0 +1,45 @@
package org.atriasoft.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to explicitly define the nullability of a parameter in an API.
*
* This annotation allows marking a parameter as required (non-null) or optional (nullable),
* overriding any other nullability considerations. It is useful in API generation frameworks
* to ensure precise validation and documentation of method parameters.
*
* <p>Usage:
* - Target: This annotation can be applied to field.
* - Retention: The annotation is retained at runtime, allowing it to be
* processed by frameworks or libraries that handle code generation logic.
*
* <p>Behavior:
* - When applied to a parameter, it explicitly marks it as optional or required in the API.
* This annotation overrides all other considerations regarding nullability.
*
* <p>Example:
* <pre>{@code
* public class User {
* @ReadOnlyField
* @ApiNotNull
* public String username;
* public String email;
* }
* }</pre>
*
* In this example, the `username` field in the `User` class is explicitly marked as non-null in the generated API.
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiNotNull {
/**
* (Optional) Specifies whether the API element can be null.
* If set to `true`, the element is required (non-null).
* If set to `false`, the element is optional (nullable).
*/
boolean value() default true;
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.apiGenerator; package org.atriasoft.archidata.annotation.apiGenerator;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -25,7 +25,7 @@ import java.lang.annotation.Target;
* the older XMLHttpRequest interface is utilized. * the older XMLHttpRequest interface is utilized.
* *
* <p>Example: * <p>Example:
* <pre>{@code * {@code
* public class SeasonService { * public class SeasonService {
* *
* @POST * @POST
@ -41,13 +41,13 @@ import java.lang.annotation.Target;
* // Upload logic * // Upload logic
* } * }
* } * }
* }</pre> * }
* *
* In this example, the uploadCover method will generate a client-side API * In this example, the uploadCover method will generate a client-side API
* with progress tracking capabilities using XMLHttpRequest. * with progress tracking capabilities using XMLHttpRequest.
* *
* <p>Generated TypeScript code example: * <p>Generated TypeScript code example:
* <pre>{@code * {@code
* export function uploadCover({ * export function uploadCover({
* restConfig, * restConfig,
* params, * params,
@ -62,8 +62,9 @@ import java.lang.annotation.Target;
* file: File, * file: File,
* }, * },
* callbacks?: RESTCallbacks, * callbacks?: RESTCallbacks,
* }): Promise<Season> {... * }): Promise<Season> {...}
* }</pre> * }
*
* *
*/ */
@Target({ ElementType.PARAMETER, ElementType.METHOD }) @Target({ ElementType.PARAMETER, ElementType.METHOD })

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -9,7 +9,15 @@ import jakarta.validation.Constraint;
import jakarta.validation.Payload; import jakarta.validation.Payload;
@Constraint(validatedBy = CheckForeignKeyValidator.class) @Constraint(validatedBy = CheckForeignKeyValidator.class)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) @Target({ ElementType.TYPE, //
ElementType.METHOD, //
ElementType.FIELD, //
ElementType.ANNOTATION_TYPE, //
ElementType.CONSTRUCTOR, //
ElementType.PARAMETER, //
ElementType.TYPE_USE, //
})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface CheckForeignKey { public @interface CheckForeignKey {
Class<?> target(); Class<?> target();

View File

@ -0,0 +1,36 @@
package org.atriasoft.archidata.annotation.checker;
import org.atriasoft.archidata.dataAccess.DataAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class CheckForeignKeyValidator implements ConstraintValidator<CheckForeignKey, Object> {
Class<?> target = null;
private final static Logger LOGGER = LoggerFactory.getLogger(CheckForeignKeyValidator.class);
@Override
public void initialize(final CheckForeignKey annotation) {
this.target = annotation.target();
}
@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
if (value == null) {
return true;
}
try {
final long count = DataAccess.count(this.target, value);
if (count != 1) {
return false;
}
} catch (final Exception e) {
LOGGER.error("Fail to access to the DB");
context.buildConstraintViolationWithTemplate("fail to access on the DB").addConstraintViolation();
return false;
}
return true;
}
}

View File

@ -1,11 +1,11 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; 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.atriasoft.archidata.dataAccess.options.CheckFunctionInterface;
/** /**
* The Checker annotation is used to specify a checker class that automatically * The Checker annotation is used to specify a checker class that automatically

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.util.Collection; import java.util.Collection;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.util.Collection; import java.util.Collection;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.checker; package org.atriasoft.archidata.annotation.checker;
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext; import jakarta.validation.ConstraintValidatorContext;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.method; package org.atriasoft.archidata.annotation.method;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.method; package org.atriasoft.archidata.annotation.method;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.annotation.security; package org.atriasoft.archidata.annotation.security;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.api; package org.atriasoft.archidata.api;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@ -21,18 +21,18 @@ import java.util.UUID;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import org.atriasoft.archidata.annotation.apiGenerator.ApiInputOptional;
import org.atriasoft.archidata.annotation.security.PermitTokenInURI;
import org.atriasoft.archidata.dataAccess.DataAccess;
import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.exception.FailException;
import org.atriasoft.archidata.filter.GenericContext;
import org.atriasoft.archidata.model.Data;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.apiGenerator.ApiInputOptional;
import org.kar.archidata.annotation.security.PermitTokenInURI;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.exception.FailException;
import org.kar.archidata.filter.GenericContext;
import org.kar.archidata.model.Data;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -157,13 +157,8 @@ public class DataResource {
return null; return null;
} }
public Data createNewData(final long tmpUID, final String originalFileName, final String sha512) protected String getMimeType(final String extension) throws IOException {
throws IOException { return switch (extension.toLowerCase()) {
// determine mime type:
Data injectedData = new Data();
String mimeType = "";
final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
mimeType = switch (extension.toLowerCase()) {
case "jpg", "jpeg" -> "image/jpeg"; case "jpg", "jpeg" -> "image/jpeg";
case "png" -> "image/png"; case "png" -> "image/png";
case "webp" -> "image/webp"; case "webp" -> "image/webp";
@ -172,6 +167,15 @@ public class DataResource {
case "webm" -> "video/webm"; case "webm" -> "video/webm";
default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'"); default -> throw new IOException("Can not find the mime type of data input: '" + extension + "'");
}; };
}
public Data createNewData(final long tmpUID, final String originalFileName, final String sha512)
throws IOException {
// determine mime type:
Data injectedData = new Data();
String mimeType = "";
final String extension = originalFileName.substring(originalFileName.lastIndexOf('.') + 1);
mimeType = getMimeType(extension);
injectedData.mimeType = mimeType; injectedData.mimeType = mimeType;
injectedData.sha512 = sha512; injectedData.sha512 = sha512;
final String tmpPath = getTmpFileInData(tmpUID); final String tmpPath = getTmpFileInData(tmpUID);
@ -369,10 +373,9 @@ public class DataResource {
} }
LOGGER.info("input size image: {}x{} type={}", inputImage.getWidth(), inputImage.getHeight(), LOGGER.info("input size image: {}x{} type={}", inputImage.getWidth(), inputImage.getHeight(),
inputImage.getType()); inputImage.getType());
final int scaledWidth = 250; final int scaledWidth = ConfigBaseVariable.getThumbnailWidth();
final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth() final int scaledHeight = (int) ((float) inputImage.getHeight() / (float) inputImage.getWidth()
* scaledWidth); * scaledWidth);
// creates output image // creates output image
final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType()); final BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, inputImage.getType());
@ -381,16 +384,10 @@ public class DataResource {
LOGGER.info("output size image: {}x{}", scaledWidth, scaledHeight); LOGGER.info("output size image: {}x{}", scaledWidth, scaledHeight);
g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null); g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);
g2d.dispose(); g2d.dispose();
for (final String data : ImageIO.getWriterFormatNames()) {
LOGGER.info("availlable format: {}", data);
}
// create the output stream: // create the output stream:
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
// TODO: check how to remove buffer file !!! here, it is not needed at all... ImageIO.write(outputImage, ConfigBaseVariable.getThumbnailFormat(), baos);
//ImageIO.write(outputImage, "JPEG", baos);
//ImageIO.write(outputImage, "png", baos);
ImageIO.write(outputImage, "WebP", baos);
} catch (final IOException e) { } catch (final IOException e) {
e.printStackTrace(); e.printStackTrace();
return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain") return Response.status(500).entity("Internal Error: resize fail: " + e.getMessage()).type("text/plain")
@ -398,12 +395,20 @@ public class DataResource {
} }
final byte[] imageData = baos.toByteArray(); final byte[] imageData = baos.toByteArray();
LOGGER.info("output length {}", imageData.length); LOGGER.info("output length {}", imageData.length);
// Response.ok(new ByteArrayInputStream(imageData)).build(); if (imageData.length == 0) {
LOGGER.error("Fail to convert image... Availlable format:");
for (final String data : ImageIO.getWriterFormatNames()) {
LOGGER.error(" - {}", data);
}
}
final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH, final Response.ResponseBuilder out = Response.ok(imageData).header(HttpHeaders.CONTENT_LENGTH,
imageData.length); imageData.length);
//out.type("image/jpeg"); try {
out.type("image/webp"); out.type(getMimeType(ConfigBaseVariable.getThumbnailFormat()));
//out.type("image/png"); } catch (final IOException ex) {
throw new FailException(Response.Status.INTERNAL_SERVER_ERROR,
"Fail to convert mime type of " + ConfigBaseVariable.getThumbnailFormat(), ex);
}
// TODO: move this in a decorator !!! // TODO: move this in a decorator !!!
final CacheControl cc = new CacheControl(); final CacheControl cc = new CacheControl();
cc.setMaxAge(3600); cc.setMaxAge(3600);

View File

@ -1,4 +1,4 @@
package org.kar.archidata.api; package org.atriasoft.archidata.api;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.api; package org.atriasoft.archidata.api;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.api; package org.atriasoft.archidata.api;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.api; package org.atriasoft.archidata.api;
import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource; import io.swagger.v3.jaxrs2.integration.resources.BaseOpenApiResource;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.backup; package org.atriasoft.archidata.backup;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,6 +1,6 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.kar.archidata.exception.FailException; import org.atriasoft.archidata.exception.FailException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.ResourceConfig;
@ -11,15 +11,16 @@ public class GenericCatcher {
public static void addAll(final ResourceConfig rc) { public static void addAll(final ResourceConfig rc) {
// Generic Json parsing error // Generic Json parsing error
rc.register(JacksonExceptionCatcher.class); rc.register(JacksonExceptionCatcher.class);
// Catch jakarta generic errors
rc.register(WebApplicationExceptionCatcher.class);
// Archidata exceptions // Archidata exceptions
rc.register(InputExceptionCatcher.class); rc.register(InputExceptionCatcher.class);
rc.register(SystemExceptionCatcher.class); rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class); rc.register(FailExceptionCatcher.class);
// generic Exception catcher // generic Exception catcher
rc.register(ExceptionCatcher.class);
rc.register(ConstraintViolationExceptionCatcher.class); rc.register(ConstraintViolationExceptionCatcher.class);
rc.register(QueryParamExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// Catch jakarta generic errors
rc.register(WebApplicationExceptionCatcher.class);
} }
} }

View File

@ -1,6 +1,6 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.kar.archidata.exception.InputException; import org.atriasoft.archidata.exception.InputException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -0,0 +1,34 @@
package org.atriasoft.archidata.catcher;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import org.glassfish.jersey.server.ParamException.QueryParamException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
public class QueryParamExceptionCatcher implements ExceptionMapper<QueryParamException> {
private static final Logger LOGGER = LoggerFactory.getLogger(QueryParamExceptionCatcher.class);
@Override
public Response toResponse(final QueryParamException exception) {
LOGGER.trace("Catch IllegalArgumentException: {}", exception.getLocalizedMessage());
final RestErrorResponse ret = build(exception);
LOGGER.error("Error OID={}", ret.oid);
return Response.status(Response.Status.BAD_REQUEST).entity(ret).type(MediaType.APPLICATION_JSON).build();
}
private RestErrorResponse build(final QueryParamException exception) {
final List<RestInputError> inputError = new ArrayList<>();
inputError.add(new RestInputError("query", exception.getParameterName(), exception.getCause().getMessage()));
final String errorType = "Error on query input='" + exception.getParameterName() + "'";
return new RestErrorResponse(Response.Status.BAD_REQUEST, Instant.now().toString(), errorType,
"Input parsing fail", inputError);
}
}

View File

@ -1,16 +1,20 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import org.atriasoft.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.annotation.Nullable;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@ApiGenerationMode @ApiGenerationMode
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RestErrorResponse { public class RestErrorResponse {
public ObjectId oid = new ObjectId(); public ObjectId oid = new ObjectId();
@NotNull @NotNull
@ -28,6 +32,7 @@ public class RestErrorResponse {
@Column(length = 0) @Column(length = 0)
final public String statusMessage; final public String statusMessage;
@Nullable
final public List<RestInputError> inputError; final public List<RestInputError> inputError;
public RestErrorResponse(final Response.Status status, final String time, final String error, final String message, public RestErrorResponse(final Response.Status status, final String time, final String error, final String message,

View File

@ -1,12 +1,15 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.validation.Path; import jakarta.validation.Path;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class RestInputError { public class RestInputError {
private static Pattern PATTERN = Pattern.compile("^([^.]+)\\.([^.]+)(\\.(.*))?"); private static Pattern PATTERN = Pattern.compile("^([^.]+)\\.([^.]+)(\\.(.*))?");
@Column(length = 0) @Column(length = 0)
@ -24,6 +27,17 @@ public class RestInputError {
public RestInputError() {} public RestInputError() {}
public RestInputError(final String argument, final String path, final String message) {
this.path = argument;
this.path = path;
this.message = message;
}
public RestInputError(final String path, final String message) {
this.path = path;
this.message = message;
}
public RestInputError(final Path path, final String message) { public RestInputError(final Path path, final String message) {
final Matcher matcher = PATTERN.matcher(path.toString()); final Matcher matcher = PATTERN.matcher(path.toString());
if (matcher.find()) { if (matcher.find()) {
@ -36,11 +50,6 @@ public class RestInputError {
this.message = message; this.message = message;
} }
public RestInputError(final String path, final String message) {
this.path = path;
this.message = message;
}
String getFullPath() { String getFullPath() {
if (this.path == null) { if (this.path == null) {
return this.argument; return this.argument;

View File

@ -1,6 +1,6 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.kar.archidata.exception.SystemException; import org.atriasoft.archidata.exception.SystemException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.catcher; package org.atriasoft.archidata.catcher;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.checker; package org.atriasoft.archidata.checker;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.Timestamp; import java.sql.Timestamp;
@ -14,21 +14,21 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.kar.archidata.annotation.AnnotationTools; import org.atriasoft.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.checker.CheckForeignKey; import org.atriasoft.archidata.annotation.checker.CheckForeignKey;
import org.kar.archidata.annotation.checker.Checker; import org.atriasoft.archidata.annotation.checker.Checker;
import org.kar.archidata.annotation.checker.CollectionItemNotNull; import org.atriasoft.archidata.annotation.checker.CollectionItemNotNull;
import org.kar.archidata.annotation.checker.CollectionItemUnique; import org.atriasoft.archidata.annotation.checker.CollectionItemUnique;
import org.kar.archidata.annotation.checker.CollectionNotEmpty; import org.atriasoft.archidata.annotation.checker.CollectionNotEmpty;
import org.kar.archidata.dataAccess.DBAccess; import org.atriasoft.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.QueryCondition; import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions; import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.options.CheckFunctionInterface; import org.atriasoft.archidata.dataAccess.options.CheckFunctionInterface;
import org.kar.archidata.dataAccess.options.CheckFunctionVoid; import org.atriasoft.archidata.dataAccess.options.CheckFunctionVoid;
import org.kar.archidata.dataAccess.options.Condition; import org.atriasoft.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.ConditionChecker; import org.atriasoft.archidata.dataAccess.options.ConditionChecker;
import org.kar.archidata.exception.DataAccessException; import org.atriasoft.archidata.exception.DataAccessException;
import org.kar.archidata.exception.InputException; import org.atriasoft.archidata.exception.InputException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -0,0 +1,53 @@
package org.atriasoft.archidata.converter.Jakarta;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Date;
import org.atriasoft.archidata.tools.DateTools;
import jakarta.annotation.Priority;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import jakarta.ws.rs.ext.Provider;
@Provider
@Priority(1)
public class DateParamConverterProvider implements ParamConverterProvider {
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(
final Class<T> rawType,
final Type genericType,
final Annotation[] annotations) {
if (rawType != Date.class) {
return null;
}
return (ParamConverter<T>) new DateParamConverter();
}
public class DateParamConverter implements ParamConverter<Date> {
@Override
public Date fromString(final String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
return DateTools.parseDate(value);
} catch (final IOException e) {
throw new IllegalArgumentException("Invalid date format. Please use ISO8601", e);
}
}
@Override
public String toString(final Date value) {
if (value == null) {
return null;
}
return DateTools.serializeMilliWithUTCTimeZone(value);
}
}
}

View File

@ -0,0 +1,52 @@
package org.atriasoft.archidata.converter.Jakarta;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.time.OffsetDateTime;
import org.atriasoft.archidata.tools.DateTools;
import jakarta.ws.rs.ext.ParamConverter;
import jakarta.ws.rs.ext.ParamConverterProvider;
import jakarta.ws.rs.ext.Provider;
@Provider
public class OffsetDateTimeParamConverterProvider implements ParamConverterProvider {
@SuppressWarnings("unchecked")
@Override
public <T> ParamConverter<T> getConverter(
final Class<T> rawType,
final Type genericType,
final Annotation[] annotations) {
if (rawType != OffsetDateTime.class) {
return null;
}
return (ParamConverter<T>) new OffsetDateTimeParamConverter();
}
public class OffsetDateTimeParamConverter implements ParamConverter<OffsetDateTime> {
@Override
public OffsetDateTime fromString(final String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
return DateTools.parseOffsetDateTime(value);
} catch (final IOException e) {
throw new IllegalArgumentException("Invalid date format. Please use ISO8601", e);
}
}
@Override
public String toString(final OffsetDateTime value) {
if (value == null) {
return null;
}
return DateTools.serializeMilliWithUTCTimeZone(value);
}
};
}

View File

@ -0,0 +1,19 @@
package org.atriasoft.archidata.converter.jackson;
import java.io.IOException;
import java.util.Date;
import org.atriasoft.archidata.tools.DateTools;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
final String value = p.getText();
final Date ret = DateTools.parseDate(value);
return ret;
}
}

View File

@ -0,0 +1,18 @@
package org.atriasoft.archidata.converter.jackson;
import java.io.IOException;
import java.util.Date;
import org.atriasoft.archidata.tools.DateTools;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class DateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider serializers)
throws IOException {
gen.writeString(DateTools.serializeMilliWithUTCTimeZone(value));
}
}

View File

@ -0,0 +1,21 @@
package org.atriasoft.archidata.converter.jackson;
import java.time.OffsetDateTime;
import java.util.Date;
import org.bson.types.ObjectId;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class JacksonModules {
public static SimpleModule getAllModules() {
final SimpleModule module = new SimpleModule();
module.addSerializer(ObjectId.class, new ObjectIdSerializer());
module.addDeserializer(ObjectId.class, new ObjectIdDeserializer());
module.addSerializer(Date.class, new DateSerializer());
module.addDeserializer(Date.class, new DateDeserializer());
module.addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer());
module.addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer());
return module;
}
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.converter.jackson; package org.atriasoft.archidata.converter.jackson;
import java.io.IOException; import java.io.IOException;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.converter.jackson; package org.atriasoft.archidata.converter.jackson;
import java.io.IOException; import java.io.IOException;

View File

@ -0,0 +1,19 @@
package org.atriasoft.archidata.converter.jackson;
import java.io.IOException;
import java.time.OffsetDateTime;
import org.atriasoft.archidata.tools.DateTools;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class OffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {
@Override
public OffsetDateTime deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException {
final String value = p.getText();
final OffsetDateTime ret = DateTools.parseOffsetDateTime(value);
return ret;
}
}

View File

@ -0,0 +1,18 @@
package org.atriasoft.archidata.converter.jackson;
import java.io.IOException;
import java.time.OffsetDateTime;
import org.atriasoft.archidata.tools.DateTools;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class OffsetDateTimeSerializer extends JsonSerializer<OffsetDateTime> {
@Override
public void serialize(final OffsetDateTime value, final JsonGenerator gen, final SerializerProvider serializers)
throws IOException {
gen.writeString(DateTools.serializeMilliWithUTCTimeZone(value));
}
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.converter.morphia; package org.atriasoft.archidata.converter.morphia;
import java.sql.Timestamp; import java.sql.Timestamp;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
/** Java does not permit to set return data (eg: integer) in the function parameter. This class permit to update a value as in/out function parameters. */ /** Java does not permit to set return data (eg: integer) in the function parameter. This class permit to update a value as in/out function parameters. */
public class CountInOut { public class CountInOut {

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
@ -6,21 +6,21 @@ import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.kar.archidata.annotation.AnnotationTools; import org.atriasoft.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName; import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.options.Condition; import org.atriasoft.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.FilterValue; import org.atriasoft.archidata.dataAccess.options.FilterValue;
import org.kar.archidata.dataAccess.options.Limit; import org.atriasoft.archidata.dataAccess.options.Limit;
import org.kar.archidata.dataAccess.options.OptionSpecifyType; import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.dataAccess.options.QueryOption; import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.dataAccess.options.TransmitKey; import org.atriasoft.archidata.dataAccess.options.TransmitKey;
import org.kar.archidata.db.DbConfig; import org.atriasoft.archidata.db.DbConfig;
import org.kar.archidata.db.DbIo; import org.atriasoft.archidata.db.DbIo;
import org.kar.archidata.db.DbIoFactory; import org.atriasoft.archidata.db.DbIoFactory;
import org.kar.archidata.db.DbIoMorphia; import org.atriasoft.archidata.db.DbIoMorphia;
import org.kar.archidata.db.DbIoSql; import org.atriasoft.archidata.db.DbIoSql;
import org.kar.archidata.exception.DataAccessException; import org.atriasoft.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ContextGenericTools; import org.atriasoft.archidata.tools.ContextGenericTools;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -185,7 +185,8 @@ public abstract class DBAccess implements Closeable {
/** @param <T> /** @param <T>
* @param data * @param data
* @param id * @param id
* @param filterValue * @param updateColomn
* @param option
* @return the affected rows. * @return the affected rows.
* @throws Exception */ * @throws Exception */
public <T, ID_TYPE> long update( public <T, ID_TYPE> long update(
@ -300,8 +301,7 @@ public abstract class DBAccess implements Closeable {
/** Delete items with the specific condition and some options. If the Entity is manage as a softDeleted model, then it is flag as removed (if not already done before). /** Delete items with the specific condition and some options. If the Entity is manage as a softDeleted model, then it is flag as removed (if not already done before).
* @param clazz Data model that might remove element. * @param clazz Data model that might remove element.
* @param condition Condition to remove elements. * @param option (Optional) Options of the request.
* @param options (Optional) Options of the request.
* @return Number of element that is removed. */ * @return Number of element that is removed. */
public long deleteWhere(final Class<?> clazz, final QueryOption... option) throws Exception { public long deleteWhere(final Class<?> clazz, final QueryOption... option) throws Exception {
final String hasDeletedFieldName = AnnotationTools.getDeletedFieldName(clazz); final String hasDeletedFieldName = AnnotationTools.getDeletedFieldName(clazz);

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -14,24 +14,26 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.annotation.CreationTimestamp;
import org.atriasoft.archidata.annotation.UpdateTimestamp;
import org.atriasoft.archidata.dataAccess.addOnMongo.AddOnManyToOne;
import org.atriasoft.archidata.dataAccess.addOnMongo.AddOnOneToMany;
import org.atriasoft.archidata.dataAccess.addOnMongo.DataAccessAddOn;
import org.atriasoft.archidata.dataAccess.options.CheckFunction;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.dataAccess.options.FilterValue;
import org.atriasoft.archidata.dataAccess.options.Limit;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OrderBy;
import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.atriasoft.archidata.db.DbIoMorphia;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.UuidUtils;
import org.bson.Document; import org.bson.Document;
import org.bson.conversions.Bson; import org.bson.conversions.Bson;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.CreationTimestamp;
import org.kar.archidata.annotation.UpdateTimestamp;
import org.kar.archidata.dataAccess.addOnMongo.AddOnManyToOne;
import org.kar.archidata.dataAccess.addOnMongo.AddOnOneToMany;
import org.kar.archidata.dataAccess.addOnMongo.DataAccessAddOn;
import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.FilterValue;
import org.kar.archidata.dataAccess.options.Limit;
import org.kar.archidata.dataAccess.options.OrderBy;
import org.kar.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.db.DbIoMorphia;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.UuidUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -128,7 +130,7 @@ public class DBAccessMorphia extends DBAccess {
return groups; return groups;
} }
protected <T> void setValuedb( protected <T> void setValueToDb(
final Class<?> type, final Class<?> type,
final T data, final T data,
final Field field, final Field field,
@ -136,7 +138,9 @@ public class DBAccessMorphia extends DBAccess {
final Document docSet, final Document docSet,
final Document docUnSet) throws Exception { final Document docUnSet) throws Exception {
if (field.get(data) == null) { if (field.get(data) == null) {
if (docUnSet != null) {
docUnSet.append(fieldName, ""); docUnSet.append(fieldName, "");
}
return; return;
} }
if (type == long.class) { if (type == long.class) {
@ -151,7 +155,7 @@ public class DBAccessMorphia extends DBAccess {
docSet.append(fieldName, field.getFloat(data)); docSet.append(fieldName, field.getFloat(data));
return; return;
} }
if (type == Double.class) { if (type == double.class) {
docSet.append(fieldName, field.getDouble(data)); docSet.append(fieldName, field.getDouble(data));
return; return;
} }
@ -196,56 +200,40 @@ public class DBAccessMorphia extends DBAccess {
docSet.append(fieldName, tmp); docSet.append(fieldName, tmp);
return; return;
} }
if (type == ObjectId.class) {
docSet.append(fieldName, tmp);
return;
}
if (type == UUID.class) { if (type == UUID.class) {
docSet.append(fieldName, tmp); docSet.append(fieldName, tmp);
return; return;
} }
if (type == Date.class) { if (type == Date.class) {
// TODO ...
/* /*
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
final Timestamp sqlDate = java.sql.Timestamp.from(((Date) tmp).toInstant()); final Timestamp sqlDate = java.sql.Timestamp.from(((Date) tmp).toInstant());
ps.setTimestamp(iii.value, sqlDate); ps.setTimestamp(iii.value, sqlDate);
}*/ */
} }
if (type == Instant.class) { if (type == Instant.class) {
/* /*
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
final String sqlDate = ((Instant) tmp).toString(); final String sqlDate = ((Instant) tmp).toString();
ps.setString(iii.value, sqlDate); ps.setString(iii.value, sqlDate);
}
*/ */
} }
if (type == LocalDate.class) { if (type == LocalDate.class) {
/* /*
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
final java.sql.Date sqlDate = java.sql.Date.valueOf((LocalDate) tmp); final java.sql.Date sqlDate = java.sql.Date.valueOf((LocalDate) tmp);
ps.setDate(iii.value, sqlDate); ps.setDate(iii.value, sqlDate);
}
*/ */
} }
if (type == LocalTime.class) { if (type == LocalTime.class) {
/* /*
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
final java.sql.Time sqlDate = java.sql.Time.valueOf((LocalTime) tmp); final java.sql.Time sqlDate = java.sql.Time.valueOf((LocalTime) tmp);
ps.setTime(iii.value, sqlDate); ps.setTime(iii.value, sqlDate);
}
*/ */
} }
throw new DataAccessException("Unknown Field Type"); docSet.append(fieldName, tmp);
//throw new DataAccessException("Unknown Field Type");
} }
public <T> void setValueFromDoc( public <T> void setValueFromDoc(
@ -265,6 +253,11 @@ public class DBAccessMorphia extends DBAccess {
field.set(data, value); field.set(data, value);
return; return;
} }
if (type == ObjectId.class) {
final ObjectId value = doc.get(fieldName, ObjectId.class);
field.set(data, value);
return;
}
if (type == Long.class || type == long.class) { if (type == Long.class || type == long.class) {
final Long value = doc.getLong(fieldName); final Long value = doc.getLong(fieldName);
field.set(data, value); field.set(data, value);
@ -349,8 +342,8 @@ public class DBAccessMorphia extends DBAccess {
final Object value = doc.get(fieldName, field.getType()); final Object value = doc.get(fieldName, field.getType());
field.set(data, value); field.set(data, value);
} else { } else {
final Object value = createObjectFromDocument(doc.get(fieldName, Document.class), field.getType(), null, final Object value = createObjectFromDocument(doc.get(fieldName, Document.class), field.getType(),
lazyCall); new QueryOptions(), lazyCall);
field.set(data, value); field.set(data, value);
} }
@ -459,32 +452,45 @@ public class DBAccessMorphia extends DBAccess {
Object uniqueId = null; Object uniqueId = null;
// real add in the BDD: // real add in the BDD:
ObjectId insertedId = null; ObjectId insertedId = null;
final List<OptionSpecifyType> specificTypes = options.get(OptionSpecifyType.class);
try { try {
final MongoCollection<Document> collection = this.db.getDatastore().getDatabase() final MongoCollection<Document> collection = this.db.getDatastore().getDatabase()
.getCollection(collectionName); .getCollection(collectionName);
final Document doc = new Document(); final Document docSet = new Document();
final Document docUnSet = new Document();
for (final Field field : clazz.getFields()) { for (final Field field : clazz.getFields()) {
// static field is only for internal global declaration ==> remove it .. // static field is only for internal global declaration ==> remove it ..
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
continue; continue;
} }
final String tableFieldName = AnnotationTools.getFieldName(field, options).inTable(); final FieldName tableFieldName = AnnotationTools.getFieldName(field, options);
Object currentInsertValue = field.get(data); Object currentInsertValue = field.get(data);
if (AnnotationTools.isPrimaryKey(field)) { if (AnnotationTools.isPrimaryKey(field)) {
primaryKeyField = field; primaryKeyField = field;
if (primaryKeyField.getType() == UUID.class) { if (primaryKeyField.getType() == UUID.class) {
final UUID uuid = UuidUtils.nextUUID(); final UUID uuid = UuidUtils.nextUUID();
uniqueId = uuid; uniqueId = uuid;
doc.append(tableFieldName, uuid); docSet.append(tableFieldName.inTable(), uuid);
continue; continue;
} else if (primaryKeyField.getType() == Long.class || primaryKeyField.getType() == long.class) { } else if (primaryKeyField.getType() == Long.class || primaryKeyField.getType() == long.class) {
// By default the MongoDB does not manage the // By default the MongoDB does not manage the
final long id = getNextSequenceLongValue(collectionName, tableFieldName); final long id = getNextSequenceLongValue(collectionName, tableFieldName.inTable());
uniqueId = id; uniqueId = id;
doc.append(tableFieldName, id); docSet.append(tableFieldName.inTable(), id);
continue; continue;
} }
LOGGER.error("TODO: Manage the ID primary key for type: "); LOGGER.error("TODO: Manage the ID primary key for type: {}=>{}", clazz.getCanonicalName(),
primaryKeyField.getType());
continue;
}
final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0;
if (createTime) {
docSet.append(tableFieldName.inTable(), Date.from(Instant.now()));
continue;
}
final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (updateTime) {
docSet.append(tableFieldName.inTable(), Date.from(Instant.now()));
continue; continue;
} }
final DataAccessAddOn addOn = findAddOnforField(field); final DataAccessAddOn addOn = findAddOnforField(field);
@ -495,19 +501,8 @@ public class DBAccessMorphia extends DBAccess {
} }
continue; continue;
} }
final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0;
if (createTime) {
doc.append(tableFieldName, Date.from(Instant.now()));
continue;
}
final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (updateTime) {
doc.append(tableFieldName, Date.from(Instant.now()));
continue;
}
if (currentInsertValue == null && !field.getClass().isPrimitive()) { if (currentInsertValue == null && !field.getClass().isPrimitive()) {
final DefaultValue[] defaultValue = field.getDeclaredAnnotationsByType(DefaultValue.class); final DefaultValue[] defaultValue = field.getDeclaredAnnotationsByType(DefaultValue.class);
LOGGER.error("TODO: convert default value in the correct value for the DB...");
if (defaultValue.length == 0) { if (defaultValue.length == 0) {
continue; continue;
} else { } else {
@ -518,9 +513,24 @@ public class DBAccessMorphia extends DBAccess {
currentInsertValue = convertDefaultField(value, field); currentInsertValue = convertDefaultField(value, field);
} }
} }
doc.append(tableFieldName, currentInsertValue); // conversion table ...
//doc.append(tableFieldName, currentInsertValue);
if (addOn != null) {
addOn.insertData(this, field, data, options, docSet, docUnSet);
} else {
final Class<?> type = field.getType();
if (!type.isPrimitive()) {
if (field.get(data) == null) {
if (currentInsertValue != null) {
docSet.append(tableFieldName.inTable(), currentInsertValue);
} }
final InsertOneResult result = collection.insertOne(doc); continue;
}
}
setValueToDb(type, data, field, tableFieldName.inTable(), docSet, null);
}
}
final InsertOneResult result = collection.insertOne(docSet);
// Get the Object of inserted object: // Get the Object of inserted object:
insertedId = result.getInsertedId().asObjectId().getValue(); insertedId = result.getInsertedId().asObjectId().getValue();
LOGGER.info("Document inserted with ID: " + insertedId); LOGGER.info("Document inserted with ID: " + insertedId);
@ -587,14 +597,14 @@ public class DBAccessMorphia extends DBAccess {
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
continue; continue;
} }
final String fieldName = AnnotationTools.getFieldName(field, options).inTable(); final FieldName fieldName = AnnotationTools.getFieldName(field, options);
// update field is not conditioned by filter: // update field is not conditioned by filter:
final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0; final boolean updateTime = field.getDeclaredAnnotationsByType(UpdateTimestamp.class).length != 0;
if (updateTime) { if (updateTime) {
docSet.append(fieldName, Date.from(Instant.now())); docSet.append(fieldName.inTable(), Date.from(Instant.now()));
continue; continue;
} }
if (!filterKey.getValues().contains(fieldName)) { if (!filterKey.getValues().contains(fieldName.inStruct())) {
continue; continue;
} else if (AnnotationTools.isGenericField(field)) { } else if (AnnotationTools.isGenericField(field)) {
continue; continue;
@ -624,12 +634,10 @@ public class DBAccessMorphia extends DBAccess {
continue; continue;
} }
} }
setValuedb(type, data, field, fieldName, docSet, docUnSet); setValueToDb(type, data, field, fieldName.inTable(), docSet, docUnSet);
} }
} }
// Do the query ... // Do the query ...
final MongoCollection<Document> collection = this.db.getDatastore().getDatabase() final MongoCollection<Document> collection = this.db.getDatastore().getDatabase()
.getCollection(collectionName); .getCollection(collectionName);
final Document actions = new Document(); final Document actions = new Document();
@ -652,7 +660,6 @@ public class DBAccessMorphia extends DBAccess {
} }
public List<String> generateSelectField(final Class<?> clazz, final QueryOptions options) throws Exception { public List<String> generateSelectField(final Class<?> clazz, final QueryOptions options) throws Exception {
// TODO: list of user select fields.
final boolean readAllfields = QueryOptions.readAllColomn(options); final boolean readAllfields = QueryOptions.readAllColomn(options);
final List<String> fieldsName = new ArrayList<>(); final List<String> fieldsName = new ArrayList<>();
@ -776,6 +783,8 @@ public class DBAccessMorphia extends DBAccess {
final Class<?> clazz, final Class<?> clazz,
final QueryOptions options, final QueryOptions options,
final List<LazyGetter> lazyCall) throws Exception { final List<LazyGetter> lazyCall) throws Exception {
final List<OptionSpecifyType> specificTypes = options.get(OptionSpecifyType.class);
LOGGER.info("createObjectFromDocument: {}", clazz.getCanonicalName());
final boolean readAllfields = QueryOptions.readAllColomn(options); final boolean readAllfields = QueryOptions.readAllColomn(options);
// TODO: manage class that is defined inside a class ==> Not manage for now... // TODO: manage class that is defined inside a class ==> Not manage for now...
Object data = null; Object data = null;
@ -790,23 +799,37 @@ public class DBAccessMorphia extends DBAccess {
"Can not find the default constructor for the class: " + clazz.getCanonicalName()); "Can not find the default constructor for the class: " + clazz.getCanonicalName());
} }
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
LOGGER.info(" Inspect field: name='{}' type='{}'", elem.getName(), elem.getType().getCanonicalName());
// static field is only for internal global declaration ==> remove it .. // static field is only for internal global declaration ==> remove it ..
if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) { if (java.lang.reflect.Modifier.isStatic(elem.getModifiers())) {
LOGGER.info(" ==> static");
continue; continue;
} }
final DataAccessAddOn addOn = findAddOnforField(elem); final DataAccessAddOn addOn = findAddOnforField(elem);
if (addOn != null && !addOn.canRetrieve(elem)) { if (addOn != null && !addOn.canRetrieve(elem)) {
LOGGER.info(" ==> Can not retreive this field");
continue; continue;
} }
final boolean notRead = AnnotationTools.isDefaultNotRead(elem); final boolean notRead = AnnotationTools.isDefaultNotRead(elem);
if (!readAllfields && notRead) { if (!readAllfields && notRead) {
LOGGER.info(" ==> Not read this element");
continue; continue;
} }
if (addOn != null) { if (addOn != null) {
LOGGER.error("TODO: Add on not managed .6. ");
addOn.fillFromDoc(this, doc, elem, data, options, lazyCall); addOn.fillFromDoc(this, doc, elem, data, options, lazyCall);
} else { } else {
setValueFromDoc(elem.getType(), data, elem, doc, lazyCall, options); Class<?> type = elem.getType();
if (type == Object.class) {
for (final OptionSpecifyType specify : specificTypes) {
if (specify.name.equals(elem.getName())) {
type = specify.clazz;
LOGGER.info("Detect overwrite of typing var={} ... '{}' => '{}'", elem.getName(),
elem.getType().getCanonicalName(), specify.clazz.getCanonicalName());
break;
}
}
}
setValueFromDoc(type, data, elem, doc, lazyCall, options);
} }
} }
return data; return data;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -14,37 +14,43 @@ import java.sql.Types;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.annotation.CreationTimestamp;
import org.atriasoft.archidata.annotation.UpdateTimestamp;
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnManyToMany;
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnManyToManyLocal;
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnManyToOne;
import org.atriasoft.archidata.dataAccess.addOnSQL.AddOnOneToMany;
import org.atriasoft.archidata.dataAccess.addOnSQL.DataAccessAddOn;
import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems;
import org.atriasoft.archidata.dataAccess.options.CheckFunction;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.dataAccess.options.DBInterfaceRoot;
import org.atriasoft.archidata.dataAccess.options.FilterValue;
import org.atriasoft.archidata.dataAccess.options.GroupBy;
import org.atriasoft.archidata.dataAccess.options.Limit;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OrderBy;
import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.atriasoft.archidata.dataAccess.options.ReadAllColumn;
import org.atriasoft.archidata.dataAccess.options.TransmitKey;
import org.atriasoft.archidata.db.DbIoSql;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.atriasoft.archidata.tools.DateTools;
import org.atriasoft.archidata.tools.UuidUtils;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.annotation.CreationTimestamp;
import org.kar.archidata.annotation.UpdateTimestamp;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToMany;
import org.kar.archidata.dataAccess.addOnSQL.AddOnManyToOne;
import org.kar.archidata.dataAccess.addOnSQL.AddOnOneToMany;
import org.kar.archidata.dataAccess.addOnSQL.DataAccessAddOn;
import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.DBInterfaceRoot;
import org.kar.archidata.dataAccess.options.FilterValue;
import org.kar.archidata.dataAccess.options.GroupBy;
import org.kar.archidata.dataAccess.options.Limit;
import org.kar.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.dataAccess.options.OrderBy;
import org.kar.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.dataAccess.options.TransmitKey;
import org.kar.archidata.db.DbIoSql;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.archidata.tools.DateTools;
import org.kar.archidata.tools.UuidUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -61,8 +67,12 @@ import jakarta.ws.rs.InternalServerErrorException;
public class DBAccessSQL extends DBAccess { public class DBAccessSQL extends DBAccess {
final static Logger LOGGER = LoggerFactory.getLogger(DBAccessSQL.class); final static Logger LOGGER = LoggerFactory.getLogger(DBAccessSQL.class);
// by default we manage some add-on that permit to manage non-native model (like json serialization, List of external key as String list...) // by default we manage some add-on that permit to manage non-native model (like json serialization, List of external key as String list...)
final static List<DataAccessAddOn> addOn = List.of(new AddOnManyToMany(), new AddOnManyToOne(), final static List<DataAccessAddOn> addOn = List.of(//
new AddOnOneToMany(), new AddOnDataJson()); new AddOnManyToMany(), //
new AddOnManyToOne(), //
new AddOnOneToMany(), //
new AddOnDataJson(), //
new AddOnManyToManyLocal());
private final DbIoSql db; private final DbIoSql db;
@ -223,16 +233,35 @@ public class DBAccessSQL extends DBAccess {
return out; return out;
} }
public byte[][] splitIntoGroupsOf12Bytes(final byte[] input) {
final int inputLength = input.length;
final int numOfGroups = (inputLength + 11) / 12; // Calculate the number of groups needed
final byte[][] groups = new byte[numOfGroups][12];
for (int i = 0; i < numOfGroups; i++) {
final int startIndex = i * 12;
final int endIndex = Math.min(startIndex + 12, inputLength);
groups[i] = Arrays.copyOfRange(input, startIndex, endIndex);
}
return groups;
}
public List<ObjectId> getListOfRawOIDs(final ResultSet rs, final int iii) throws SQLException, DataAccessException { public List<ObjectId> getListOfRawOIDs(final ResultSet rs, final int iii) throws SQLException, DataAccessException {
final byte[] trackString = rs.getBytes(iii); final byte[] trackString = rs.getBytes(iii);
if (rs.wasNull()) { if (rs.wasNull()) {
return null; return null;
} }
final byte[][] elements = splitIntoGroupsOf16Bytes(trackString); final byte[][] elements = splitIntoGroupsOf12Bytes(trackString);
final List<ObjectId> out = new ArrayList<>(); final List<ObjectId> out = new ArrayList<>();
for (final byte[] elem : elements) { for (final byte[] elem : elements) {
try {
final ObjectId tmp = new ObjectId(elem); final ObjectId tmp = new ObjectId(elem);
out.add(tmp); out.add(tmp);
} catch (final IllegalArgumentException ex) {
ex.printStackTrace();
LOGGER.error("Fail to parse the OID element: {}", elem);
}
} }
return out; return out;
} }
@ -259,8 +288,81 @@ public class DBAccessSQL extends DBAccess {
final CountInOut iii, final CountInOut iii,
final Field field, final Field field,
final PreparedStatement ps) throws Exception { final PreparedStatement ps) throws Exception {
if (type == ObjectId.class) { if (type == long.class) {
ps.setLong(iii.value, field.getLong(data));
iii.inc();
return;
}
if (type == int.class) {
ps.setInt(iii.value, field.getInt(data));
iii.inc();
return;
}
if (type == float.class) {
ps.setFloat(iii.value, field.getFloat(data));
iii.inc();
return;
}
if (type == double.class) {
ps.setDouble(iii.value, field.getDouble(data));
iii.inc();
return;
}
if (type == boolean.class) {
ps.setBoolean(iii.value, field.getBoolean(data));
iii.inc();
return;
}
final Object tmp = field.get(data); final Object tmp = field.get(data);
if (type.isEnum()) {
if (tmp == null) {
ps.setNull(iii.value, Types.VARCHAR);
} else {
ps.setString(iii.value, tmp.toString());
}
} else if (type == Long.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.BIGINT);
} else {
ps.setLong(iii.value, (Long) tmp);
}
} else if (type == Integer.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setInt(iii.value, (Integer) tmp);
}
} else if (type == Float.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.FLOAT);
} else {
ps.setFloat(iii.value, (Float) tmp);
}
} else if (type == Double.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.DOUBLE);
} else {
ps.setDouble(iii.value, (Double) tmp);
}
} else if (type == Boolean.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setBoolean(iii.value, (Boolean) tmp);
}
} else if (type == String.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.VARCHAR);
} else {
ps.setString(iii.value, (String) tmp);
}
} else if (type == Timestamp.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setTimestamp(iii.value, (Timestamp) tmp);
}
} else if (type == ObjectId.class) {
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.BINARY); ps.setNull(iii.value, Types.BINARY);
} else { } else {
@ -268,75 +370,31 @@ public class DBAccessSQL extends DBAccess {
ps.setBytes(iii.value, dataByte); ps.setBytes(iii.value, dataByte);
} }
} else if (type == UUID.class) { } else if (type == UUID.class) {
final Object tmp = field.get(data);
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.BINARY); ps.setNull(iii.value, Types.BINARY);
} else { } else {
final byte[] dataByte = UuidUtils.asBytes((UUID) tmp); final byte[] dataByte = UuidUtils.asBytes((UUID) tmp);
ps.setBytes(iii.value, dataByte); ps.setBytes(iii.value, dataByte);
} }
} else if (type == Long.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.BIGINT);
} else {
ps.setLong(iii.value, (Long) tmp);
}
} else if (type == long.class) {
ps.setLong(iii.value, field.getLong(data));
} else if (type == Integer.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setInt(iii.value, (Integer) tmp);
}
} else if (type == int.class) {
ps.setInt(iii.value, field.getInt(data));
} else if (type == Float.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.FLOAT);
} else {
ps.setFloat(iii.value, (Float) tmp);
}
} else if (type == float.class) {
ps.setFloat(iii.value, field.getFloat(data));
} else if (type == Double.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.DOUBLE);
} else {
ps.setDouble(iii.value, (Double) tmp);
}
} else if (type == Double.class) {
ps.setDouble(iii.value, field.getDouble(data));
} else if (type == Boolean.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setBoolean(iii.value, (Boolean) tmp);
}
} else if (type == boolean.class) {
ps.setBoolean(iii.value, field.getBoolean(data));
} else if (type == Timestamp.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
ps.setTimestamp(iii.value, (Timestamp) tmp);
}
} else if (type == Date.class) { } else if (type == Date.class) {
final Object tmp = field.get(data);
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER); ps.setNull(iii.value, Types.INTEGER);
} else { } else {
final Timestamp sqlDate = java.sql.Timestamp.from(((Date) tmp).toInstant()); final OffsetDateTime offsetDateTime = ((Date) tmp).toInstant().atZone(ZoneId.systemDefault())
.toOffsetDateTime();
final Timestamp sqlDate = java.sql.Timestamp
.from(offsetDateTime.withOffsetSameInstant(ZoneOffset.UTC).toInstant());
ps.setTimestamp(iii.value, sqlDate);
}
} else if (type == OffsetDateTime.class) {
if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER);
} else {
final Timestamp sqlDate = java.sql.Timestamp
.from(((OffsetDateTime) tmp).withOffsetSameInstant(ZoneOffset.UTC).toInstant());
ps.setTimestamp(iii.value, sqlDate); ps.setTimestamp(iii.value, sqlDate);
} }
} else if (type == Instant.class) { } else if (type == Instant.class) {
final Object tmp = field.get(data);
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER); ps.setNull(iii.value, Types.INTEGER);
} else { } else {
@ -344,7 +402,6 @@ public class DBAccessSQL extends DBAccess {
ps.setString(iii.value, sqlDate); ps.setString(iii.value, sqlDate);
} }
} else if (type == LocalDate.class) { } else if (type == LocalDate.class) {
final Object tmp = field.get(data);
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER); ps.setNull(iii.value, Types.INTEGER);
} else { } else {
@ -352,27 +409,12 @@ public class DBAccessSQL extends DBAccess {
ps.setDate(iii.value, sqlDate); ps.setDate(iii.value, sqlDate);
} }
} else if (type == LocalTime.class) { } else if (type == LocalTime.class) {
final Object tmp = field.get(data);
if (tmp == null) { if (tmp == null) {
ps.setNull(iii.value, Types.INTEGER); ps.setNull(iii.value, Types.INTEGER);
} else { } else {
final java.sql.Time sqlDate = java.sql.Time.valueOf((LocalTime) tmp); final java.sql.Time sqlDate = java.sql.Time.valueOf((LocalTime) tmp);
ps.setTime(iii.value, sqlDate); ps.setTime(iii.value, sqlDate);
} }
} else if (type == String.class) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.VARCHAR);
} else {
ps.setString(iii.value, (String) tmp);
}
} else if (type.isEnum()) {
final Object tmp = field.get(data);
if (tmp == null) {
ps.setNull(iii.value, Types.VARCHAR);
} else {
ps.setString(iii.value, tmp.toString());
}
} else { } else {
throw new DataAccessException("Unknown Field Type: " + type.getCanonicalName()); throw new DataAccessException("Unknown Field Type: " + type.getCanonicalName());
} }
@ -501,7 +543,9 @@ public class DBAccessSQL extends DBAccess {
if (rs.wasNull()) { if (rs.wasNull()) {
field.set(data, null); field.set(data, null);
} else { } else {
field.set(data, Date.from(tmp.toInstant())); final OffsetDateTime odt = tmp.toInstant().atOffset(ZoneOffset.UTC);
odt.atZoneSameInstant(ZoneId.systemDefault());
field.set(data, Date.from(odt.toInstant()));
countNotNull.inc(); countNotNull.inc();
} }
} catch (final SQLException ex) { } catch (final SQLException ex) {
@ -516,6 +560,28 @@ public class DBAccessSQL extends DBAccess {
countNotNull.inc(); countNotNull.inc();
} }
} }
} else if (type == OffsetDateTime.class) {
try {
final Timestamp tmp = rs.getTimestamp(count.value);
if (rs.wasNull()) {
field.set(data, null);
} else {
final OffsetDateTime odt = tmp.toInstant().atOffset(ZoneOffset.UTC);
field.set(data, odt);
countNotNull.inc();
}
} catch (final SQLException ex) {
final String tmp = rs.getString(count.value);
LOGGER.error("Fail to parse the SQL time !!! {}", tmp);
if (rs.wasNull()) {
field.set(data, null);
} else {
final OffsetDateTime date = DateTools.parseOffsetDateTime(tmp);
LOGGER.error("Fail to parse the SQL time !!! {}", date);
field.set(data, date);
countNotNull.inc();
}
}
} else if (type == Instant.class) { } else if (type == Instant.class) {
final String tmp = rs.getString(count.value); final String tmp = rs.getString(count.value);
if (rs.wasNull()) { if (rs.wasNull()) {
@ -882,12 +948,14 @@ public class DBAccessSQL extends DBAccess {
continue; continue;
} }
final DataAccessAddOn addOn = findAddOnforField(field); final DataAccessAddOn addOn = findAddOnforField(field);
if (addOn != null && !addOn.canInsert(field)) { if (addOn != null) {
if (addOn.isInsertAsync(field)) { if (addOn.isInsertAsync(field)) {
asyncFieldUpdate.add(field); asyncFieldUpdate.add(field);
} }
if (!addOn.canInsert(field)) {
continue; continue;
} }
}
final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0; final boolean createTime = field.getDeclaredAnnotationsByType(CreationTimestamp.class).length != 0;
if (createTime) { if (createTime) {
continue; continue;
@ -1098,6 +1166,31 @@ public class DBAccessSQL extends DBAccess {
query.append("UPDATE `"); query.append("UPDATE `");
query.append(tableName); query.append(tableName);
query.append("` SET "); query.append("` SET ");
//Some mode need to get the previous data to perform a correct update...
boolean needPreviousValues = false;
for (final Field field : clazz.getFields()) {
// field is only for internal global declaration ==> remove it ..
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
continue;
}
final FieldName name = AnnotationTools.getFieldName(field, options);
if (!filter.getValues().contains(name.inStruct())) {
continue;
} else if (AnnotationTools.isGenericField(field)) {
continue;
}
final DataAccessAddOn addOn = findAddOnforField(field);
if (addOn != null && addOn.isPreviousDataNeeded(field)) {
needPreviousValues = true;
break;
}
}
Object previousData = null;
if (needPreviousValues) {
final List<TransmitKey> transmitKey = options.get(TransmitKey.class);
previousData = this.get(data.getClass(), transmitKey.get(0).getKey(), new AccessDeletedItems(),
new ReadAllColumn());
}
boolean firstField = true; boolean firstField = true;
for (final Field field : clazz.getFields()) { for (final Field field : clazz.getFields()) {
@ -1112,18 +1205,20 @@ public class DBAccessSQL extends DBAccess {
continue; continue;
} }
final DataAccessAddOn addOn = findAddOnforField(field); final DataAccessAddOn addOn = findAddOnforField(field);
if (addOn != null && !addOn.canInsert(field)) { if (addOn != null) {
if (addOn.isInsertAsync(field)) { if (addOn.isUpdateAsync(field)) {
final List<TransmitKey> transmitKey = options.get(TransmitKey.class); final List<TransmitKey> transmitKey = options.get(TransmitKey.class);
if (transmitKey.size() != 1) { if (transmitKey.size() != 1) {
throw new DataAccessException( throw new DataAccessException(
"Fail to transmit Key to update the async update... (must have only 1)"); "Fail to transmit Key to update the async update... (must have only 1)");
} }
addOn.asyncUpdate(this, tableName, transmitKey.get(0).getKey(), field, field.get(data), addOn.asyncUpdate(this, previousData, tableName, transmitKey.get(0).getKey(), field,
asyncActions, options); field.get(data), asyncActions, options);
} }
if (!addOn.canInsert(field)) {
continue; continue;
} }
}
if (!field.getClass().isPrimitive()) { if (!field.getClass().isPrimitive()) {
final Object tmp = field.get(data); final Object tmp = field.get(data);
if (tmp == null && field.getDeclaredAnnotationsByType(DefaultValue.class).length != 0) { if (tmp == null && field.getDeclaredAnnotationsByType(DefaultValue.class).length != 0) {
@ -1147,7 +1242,6 @@ public class DBAccessSQL extends DBAccess {
query.append(" "); query.append(" ");
final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz); final String deletedFieldName = AnnotationTools.getDeletedFieldName(clazz);
condition.whereAppendQuery(query, tableName, null, deletedFieldName); condition.whereAppendQuery(query, tableName, null, deletedFieldName);
// If the first field is not set, then nothing to update n the main base: // If the first field is not set, then nothing to update n the main base:
if (!firstField) { if (!firstField) {
LOGGER.debug("generate update query: '{}'", query.toString()); LOGGER.debug("generate update query: '{}'", query.toString());
@ -1183,6 +1277,9 @@ public class DBAccessSQL extends DBAccess {
addOn.insertData(this, ps, field, data, iii); addOn.insertData(this, ps, field, data, iii);
} }
} }
for (final LazyGetter action : asyncActions) {
action.doRequest();
}
condition.injectQuery(this, ps, iii); condition.injectQuery(this, ps, iii);
final int out = ps.executeUpdate(); final int out = ps.executeUpdate();
return out; return out;
@ -1191,9 +1288,6 @@ public class DBAccessSQL extends DBAccess {
} catch (final SQLException ex) { } catch (final SQLException ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
for (final LazyGetter action : asyncActions) {
action.doRequest();
}
return 0L; return 0L;
} }
@ -1276,7 +1370,7 @@ public class DBAccessSQL extends DBAccess {
) throws Exception { ) throws Exception {
final boolean readAllfields = QueryOptions.readAllColomn(options); final boolean readAllfields = QueryOptions.readAllColomn(options);
final String tableName = AnnotationTools.getTableName(clazz, options); final String tableName = AnnotationTools.getTableName(clazz, options);
final String primaryKey = AnnotationTools.getPrimaryKeyField(clazz).getName(); final String primaryKey = AnnotationTools.getFieldNameRaw(AnnotationTools.getPrimaryKeyField(clazz));
boolean firstField = true; boolean firstField = true;
for (final Field elem : clazz.getFields()) { for (final Field elem : clazz.getFields()) {
@ -1364,7 +1458,7 @@ public class DBAccessSQL extends DBAccess {
final T out = (T) data; final T out = (T) data;
outs.add(out); outs.add(out);
} }
LOGGER.info("Async calls: {}", lazyCall.size()); LOGGER.trace("Async calls: {}", lazyCall.size());
for (final LazyGetter elem : lazyCall) { for (final LazyGetter elem : lazyCall) {
elem.doRequest(); elem.doRequest();
} }

View File

@ -1,11 +1,11 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.options.Condition; import org.atriasoft.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.QueryOption; import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.exception.DataAccessException; import org.atriasoft.archidata.exception.DataAccessException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -111,12 +111,6 @@ public class DataAccess {
} }
} }
/** @param <T>
* @param data
* @param id
* @param filterValue
* @return the affected rows.
* @throws Exception */
public static <T, ID_TYPE> long update( public static <T, ID_TYPE> long update(
final T data, final T data,
final ID_TYPE id, final ID_TYPE id,
@ -225,7 +219,6 @@ public class DataAccess {
/** Delete items with the specific condition and some options. If the Entity is manage as a softDeleted model, then it is flag as removed (if not already done before). /** Delete items with the specific condition and some options. If the Entity is manage as a softDeleted model, then it is flag as removed (if not already done before).
* @param clazz Data model that might remove element. * @param clazz Data model that might remove element.
* @param condition Condition to remove elements.
* @param options (Optional) Options of the request. * @param options (Optional) Options of the request.
* @return Number of element that is removed. */ * @return Number of element that is removed. */
public static long deleteWhere(final Class<?> clazz, final QueryOption... options) throws Exception { public static long deleteWhere(final Class<?> clazz, final QueryOption... options) throws Exception {

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.io.IOException; import java.io.IOException;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -16,16 +16,16 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.kar.archidata.dataAccess.exportTools.TableQuery; import org.atriasoft.archidata.dataAccess.exportTools.TableQuery;
import org.kar.archidata.dataAccess.exportTools.TableQueryTypes; import org.atriasoft.archidata.dataAccess.exportTools.TableQueryTypes;
import org.kar.archidata.dataAccess.options.Condition; import org.atriasoft.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.GroupBy; import org.atriasoft.archidata.dataAccess.options.GroupBy;
import org.kar.archidata.dataAccess.options.Limit; import org.atriasoft.archidata.dataAccess.options.Limit;
import org.kar.archidata.dataAccess.options.OrderBy; import org.atriasoft.archidata.dataAccess.options.OrderBy;
import org.kar.archidata.dataAccess.options.QueryOption; import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.exception.DataAccessException; import org.atriasoft.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ContextGenericTools; import org.atriasoft.archidata.tools.ContextGenericTools;
import org.kar.archidata.tools.DateTools; import org.atriasoft.archidata.tools.DateTools;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.Timestamp; import java.sql.Timestamp;
@ -10,16 +10,16 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.CreationTimestamp;
import org.atriasoft.archidata.annotation.DataIfNotExists;
import org.atriasoft.archidata.annotation.UpdateTimestamp;
import org.atriasoft.archidata.dataAccess.addOnSQL.DataAccessAddOn;
import org.atriasoft.archidata.dataAccess.options.CreateDropTable;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.CreationTimestamp;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.UpdateTimestamp;
import org.kar.archidata.dataAccess.addOnSQL.DataAccessAddOn;
import org.kar.archidata.dataAccess.options.CreateDropTable;
import org.kar.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
// Mark as deprecated while the concept is not ready ... // Mark as deprecated while the concept is not ready ...
@Deprecated @Deprecated

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
public interface LazyGetter { public interface LazyGetter {
void doRequest() throws Exception; void doRequest() throws Exception;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.List; import java.util.List;

View File

@ -1,12 +1,12 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.options.AccessDeletedItems; import org.atriasoft.archidata.dataAccess.options.AccessDeletedItems;
import org.kar.archidata.dataAccess.options.CreateDropTable; import org.atriasoft.archidata.dataAccess.options.CreateDropTable;
import org.kar.archidata.dataAccess.options.QueryOption; import org.atriasoft.archidata.dataAccess.options.QueryOption;
import org.kar.archidata.dataAccess.options.ReadAllColumn; import org.atriasoft.archidata.dataAccess.options.ReadAllColumn;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess; package org.atriasoft.archidata.dataAccess;
import java.sql.ResultSet; import java.sql.ResultSet;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.addOnMongo; package org.atriasoft.archidata.dataAccess.addOnMongo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -6,23 +6,23 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccess;
import org.atriasoft.archidata.dataAccess.DBAccessMorphia;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryAnd;
import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.addOnSQL.model.LinkTableGeneric;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.bson.Document; import org.bson.Document;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DBAccessMorphia;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.addOnSQL.model.LinkTableGeneric;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -173,34 +173,6 @@ public class AddOnManyToMany implements DataAccessAddOn {
count.inc(); count.inc();
} }
@Override
public void generateQuery(
@NotNull final String tableName,
@NotNull final String primaryKey,
@NotNull final Field field,
@NotNull final StringBuilder querySelect,
@NotNull final StringBuilder query,
@NotNull final String name,
@NotNull final CountInOut count,
final QueryOptions options) throws Exception {
if (field.getType() != List.class) {
return;
}
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
if (objectClass == Long.class || objectClass == UUID.class) {
generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options);
}
final ManyToMany decorators = field.getDeclaredAnnotation(ManyToMany.class);
if (decorators == null) {
return;
}
if (objectClass == decorators.targetEntity()) {
generateConcatQuery(tableName, primaryKey, field, querySelect, query, name, count, options);
}
}
@Override @Override
public void fillFromDoc( public void fillFromDoc(
final DBAccessMorphia ioDb, final DBAccessMorphia ioDb,

View File

@ -1,22 +1,21 @@
package org.kar.archidata.dataAccess.addOnMongo; package org.atriasoft.archidata.dataAccess.addOnMongo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.DBAccessMorphia;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.bson.Document; import org.bson.Document;
import org.kar.archidata.annotation.AnnotationTools; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccessMorphia;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryOptions;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotNull;
public class AddOnManyToOne implements DataAccessAddOn { public class AddOnManyToOne implements DataAccessAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class); static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToMany.class);
@ -52,7 +51,7 @@ public class AddOnManyToOne implements DataAccessAddOn {
final Document docUnSet) throws Exception { final Document docUnSet) throws Exception {
final FieldName fieldName = AnnotationTools.getFieldName(field, options); final FieldName fieldName = AnnotationTools.getFieldName(field, options);
final Object data = field.get(rootObject); final Object data = field.get(rootObject);
if (field.get(data) == null) { if (data == null) {
docUnSet.append(fieldName.inTable(), ""); docUnSet.append(fieldName.inTable(), "");
return; return;
} else if (field.getType() == Long.class) { } else if (field.getType() == Long.class) {
@ -70,6 +69,9 @@ public class AddOnManyToOne implements DataAccessAddOn {
} else if (field.getType() == UUID.class) { } else if (field.getType() == UUID.class) {
final UUID dataTyped = (UUID) data; final UUID dataTyped = (UUID) data;
docSet.append(fieldName.inTable(), dataTyped); docSet.append(fieldName.inTable(), dataTyped);
} else if (field.getType() == ObjectId.class) {
final ObjectId dataTyped = (ObjectId) data;
docSet.append(fieldName.inTable(), dataTyped);
} else { } else {
final Field idField = AnnotationTools.getFieldOfId(field.getType()); final Field idField = AnnotationTools.getFieldOfId(field.getType());
final Object uid = idField.get(data); final Object uid = idField.get(data);
@ -84,7 +86,8 @@ public class AddOnManyToOne implements DataAccessAddOn {
@Override @Override
public boolean canInsert(final Field field) { public boolean canInsert(final Field field) {
if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class
|| field.getType() == String.class || field.getType() == UUID.class) { || field.getType() == String.class || field.getType() == UUID.class
|| field.getType() == ObjectId.class) {
return true; return true;
} }
final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class);
@ -103,7 +106,7 @@ public class AddOnManyToOne implements DataAccessAddOn {
public boolean canRetrieve(final Field field) { public boolean canRetrieve(final Field field) {
final Class<?> classType = field.getType(); final Class<?> classType = field.getType();
if (classType == Long.class || classType == Integer.class || classType == Short.class if (classType == Long.class || classType == Integer.class || classType == Short.class
|| classType == String.class || classType == UUID.class) { || classType == String.class || classType == UUID.class || classType == ObjectId.class) {
return true; return true;
} }
final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class); final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class);
@ -113,36 +116,6 @@ public class AddOnManyToOne implements DataAccessAddOn {
return false; return false;
} }
@Override
public void generateQuery(
@NotNull final String tableName,
@NotNull final String primaryKey,
@NotNull final Field field,
@NotNull final StringBuilder querySelect,
@NotNull final StringBuilder query,
@NotNull final String name,
@NotNull final CountInOut count,
final QueryOptions options) throws Exception {
if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class
|| field.getType() == String.class || field.getType() == UUID.class) {
querySelect.append(" ");
querySelect.append(tableName);
querySelect.append(".");
querySelect.append(name);
count.inc();
return;
}
final ManyToOne decorators = field.getDeclaredAnnotation(ManyToOne.class);
if (field.getType() == decorators.targetEntity()) {
// no eager possible for no sql
querySelect.append(" ");
querySelect.append(tableName);
querySelect.append(".");
querySelect.append(name);
count.inc();
}
}
@Override @Override
public void fillFromDoc( public void fillFromDoc(
final DBAccessMorphia ioDb, final DBAccessMorphia ioDb,
@ -159,7 +132,8 @@ public class AddOnManyToOne implements DataAccessAddOn {
} }
// local field to manage no remote object to retrieve. // local field to manage no remote object to retrieve.
if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class if (field.getType() == Long.class || field.getType() == Integer.class || field.getType() == Short.class
|| field.getType() == String.class || field.getType() == UUID.class) { || field.getType() == String.class || field.getType() == UUID.class
|| field.getType() == ObjectId.class) {
ioDb.setValueFromDoc(field.getType(), data, field, doc, lazyCall, options); ioDb.setValueFromDoc(field.getType(), data, field, doc, lazyCall, options);
return; return;
} }
@ -174,9 +148,8 @@ public class AddOnManyToOne implements DataAccessAddOn {
final Class<?> remotePrimaryKeyType = remotePrimaryKeyField.getType(); final Class<?> remotePrimaryKeyType = remotePrimaryKeyField.getType();
if (remotePrimaryKeyType == Long.class) { if (remotePrimaryKeyType == Long.class) {
// here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ...
final Long foreignKey = doc.getLong(fieldName); final Long foreignKey = doc.getLong(fieldName.inTable());
if (foreignKey != null) { if (foreignKey != null) {
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
final LazyGetter lambda = () -> { final LazyGetter lambda = () -> {
// TODO: update to have get with abstract types .... // TODO: update to have get with abstract types ....
final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey);
@ -189,9 +162,22 @@ public class AddOnManyToOne implements DataAccessAddOn {
} }
} else if (remotePrimaryKeyType == UUID.class) { } else if (remotePrimaryKeyType == UUID.class) {
// here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ... // here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ...
final UUID foreignKey = doc.get(fieldName, UUID.class); final UUID foreignKey = doc.get(fieldName.inTable(), UUID.class);
if (foreignKey != null) {
final LazyGetter lambda = () -> {
// TODO: update to have get with abstract types ....
final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey);
if (foreignData == null) {
return;
}
field.set(data, foreignData);
};
lazyCall.add(lambda);
}
} else if (remotePrimaryKeyType == ObjectId.class) {
// here we have the field, the data and the the remote value ==> can create callback that generate the update of the value ...
final ObjectId foreignKey = doc.get(fieldName.inTable(), ObjectId.class);
if (foreignKey != null) { if (foreignKey != null) {
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
final LazyGetter lambda = () -> { final LazyGetter lambda = () -> {
// TODO: update to have get with abstract types .... // TODO: update to have get with abstract types ....
final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey); final Object foreignData = ioDb.get(decorators.targetEntity(), foreignKey);
@ -221,7 +207,7 @@ public class AddOnManyToOne implements DataAccessAddOn {
final QueryOptions options) throws Exception { final QueryOptions options) throws Exception {
final Class<?> classType = field.getType(); final Class<?> classType = field.getType();
if (classType == Long.class || classType == Integer.class || classType == Short.class if (classType == Long.class || classType == Integer.class || classType == Short.class
|| classType == String.class || classType == UUID.class) { || classType == String.class || classType == UUID.class || classType == ObjectId.class) {
DataFactory.createTablesSpecificType(tableName, primaryField, field, mainTableBuilder, preActionList, DataFactory.createTablesSpecificType(tableName, primaryField, field, mainTableBuilder, preActionList,
postActionList, createIfNotExist, createDrop, fieldId, classType, options); postActionList, createIfNotExist, createDrop, fieldId, classType, options);
} else { } else {

View File

@ -0,0 +1,166 @@
package org.atriasoft.archidata.dataAccess.addOnMongo;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.DBAccessMorphia;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.persistence.OneToMany;
public class AddOnOneToMany implements DataAccessAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnOneToMany.class);
static final String SEPARATOR_LONG = "-";
@Override
public Class<?> getAnnotationClass() {
return OneToMany.class;
}
@Override
public boolean isCompatibleField(final Field field) {
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
return decorators != null;
}
@Override
public void insertData(
final DBAccessMorphia ioDb,
final Field field,
final Object rootObject,
final QueryOptions options,
final Document docSet,
final Document docUnSet) throws Exception {
throw new IllegalAccessException("Can not generate an inset of @OneToMany");
}
@Override
public boolean canInsert(final Field field) {
return false;
}
@Override
public boolean isInsertAsync(final Field field) throws Exception {
// TODO: can be implemented later...
return false;
}
@Override
public boolean canRetrieve(final Field field) {
if (field.getType() != List.class) {
return false;
}
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) {
return true;
}
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
if (decorators == null) {
return false;
}
if (decorators.targetEntity() == objectClass) {
return true;
}
return false;
}
// in first implementation we did not keep the data in the 2 Objects, bun we will do it after to have a faster table interactions.
@Override
public void fillFromDoc(
final DBAccessMorphia ioDb,
final Document doc,
final Field field,
final Object data,
final QueryOptions options,
final List<LazyGetter> lazyCall) throws Exception {
if (field.getType() != List.class) {
LOGGER.error("Can not OneToMany with other than List Model: {}", field.getType().getCanonicalName());
return;
}
final FieldName fieldName = AnnotationTools.getFieldName(field, options);
// in step 1 the fields are not stored in the local element
// if (!doc.containsKey(fieldName.inTable())) {
// field.set(data, null);
// return;
// }
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
final OneToMany decorators = field.getDeclaredAnnotation(OneToMany.class);
if (decorators == null) {
return;
}
if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) {
if (true) {
// DEVELOPMENT step 1 we search all the element in the list:
// get the curentObject primary key
final Field primaryField = AnnotationTools.getPrimaryKeyField(data.getClass());
final String primaryKeyName = AnnotationTools.getFieldNameRaw(primaryField);
final Object primaryKey = doc.get(primaryKeyName, primaryField.getType());
// get the remotes objects
final List<?> returnValue = ioDb.getsWhere(decorators.targetEntity(),
new Condition(new QueryCondition(decorators.mappedBy(), "=", primaryKey)));
// extract the primary key of the remote objects
final Field remotePrimaryField = AnnotationTools.getPrimaryKeyField(decorators.targetEntity());
final String remotePrimaryKeyName = AnnotationTools.getFieldNameRaw(remotePrimaryField);
final List<Object> listOfRemoteKeys = new ArrayList<>();
for (final var item : returnValue) {
listOfRemoteKeys.add(remotePrimaryField.get(item));
}
// inject in the current data field
if (listOfRemoteKeys.size() != 0) {
field.set(data, listOfRemoteKeys);
}
} else {
// DEVELOPMENT In step 2 this will work well:
final Object value = doc.get(fieldName.inTable(), field.getType());
field.set(data, value);
}
return;
}
if (objectClass == decorators.targetEntity()) {
// Maybe in a second step we do not like this but this way is efficient too.
// get the curentObject primary key
final Field primaryField = AnnotationTools.getPrimaryKeyField(data.getClass());
final String primaryKeyName = AnnotationTools.getFieldNameRaw(primaryField);
final Object primaryKey = doc.get(primaryKeyName, primaryField.getType());
// get the remotes objects
final List<?> returnValue = ioDb.getsWhere(decorators.targetEntity(),
new Condition(new QueryCondition(decorators.mappedBy(), "=", primaryKey)));
// inject in the current data field
if (returnValue.size() != 0) {
field.set(data, returnValue);
}
}
}
// TODO : refacto this table to manage a generic table with dynamic name to be serialize with the default system
@Override
public void createTables(
final String tableName,
final Field primaryField,
final Field field,
final StringBuilder mainTableBuilder,
final List<String> preActionList,
final List<String> postActionList,
final boolean createIfNotExist,
final boolean createDrop,
final int fieldId,
final QueryOptions options) throws Exception {
// This is a remote field ==> nothing to generate (it is stored in the remote object
}
}

View File

@ -1,16 +1,13 @@
package org.kar.archidata.dataAccess.addOnMongo; package org.atriasoft.archidata.dataAccess.addOnMongo;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.atriasoft.archidata.dataAccess.DBAccessMorphia;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.bson.Document; import org.bson.Document;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccessMorphia;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryOptions;
import jakarta.validation.constraints.NotNull;
public interface DataAccessAddOn { public interface DataAccessAddOn {
/** Get the Class of the declaration annotation /** Get the Class of the declaration annotation
@ -29,12 +26,6 @@ public interface DataAccessAddOn {
* @return True of the field is manage by the current Add-on. */ * @return True of the field is manage by the current Add-on. */
boolean isCompatibleField(Field elem); boolean isCompatibleField(Field elem);
/** Insert data in the specific field (the field must be in the current db, otherwiise it does not work at all.
* @param ps DB statement interface.
* @param data The date to inject.
* @param iii The index of injection
* @return the new index of injection in case of multiple value management
* @throws SQLException */
void insertData( void insertData(
final DBAccessMorphia ioDb, final DBAccessMorphia ioDb,
final Field field, final Field field,
@ -57,16 +48,6 @@ public interface DataAccessAddOn {
return false; return false;
} }
void generateQuery(
@NotNull String tableName,
@NotNull final String primaryKey,
@NotNull Field field,
@NotNull final StringBuilder querySelect,
@NotNull final StringBuilder query,
@NotNull String name,
@NotNull CountInOut count,
QueryOptions options) throws Exception;
// Return the number of colomn read // Return the number of colomn read
void fillFromDoc( void fillFromDoc(
final DBAccessMorphia ioDb, final DBAccessMorphia ioDb,
@ -78,14 +59,7 @@ public interface DataAccessAddOn {
throws Exception, SQLException, IllegalArgumentException, IllegalAccessException; throws Exception, SQLException, IllegalArgumentException, IllegalAccessException;
/** Create associated table of the specific element. /** Create associated table of the specific element.
* @param tableName */
* @param elem
* @param mainTableBuilder
* @param ListOtherTables
* @param createIfNotExist
* @param createDrop
* @param fieldId
* @throws Exception */
void createTables( void createTables(
String tableName, String tableName,
final Field primaryField, final Field primaryField,

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.addOnSQL; package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -10,23 +10,22 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.annotation.DataJson;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccess;
import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.addOnSQL.model.TableCoversGeneric;
import org.atriasoft.archidata.dataAccess.options.OptionRenameColumn;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.ContextGenericTools;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DBAccessMorphia;
import org.kar.archidata.dataAccess.DBAccessSQL;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.addOnSQL.model.TableCoversGeneric;
import org.kar.archidata.dataAccess.options.OptionRenameColumn;
import org.kar.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ContextGenericTools;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -220,68 +219,63 @@ public class AddOnDataJson implements DataAccessAddOn {
public static void addLink( public static void addLink(
final DBAccess ioDb, final DBAccess ioDb,
final Class<?> clazz, final Class<?> clazz,
final String columnId, String clazzPrimaryKeyName,
final Object id, final Object clazzPrimaryKeyValue,
final String columnList, final String fieldNameToUpdate,
final Object remoteKey) throws Exception { final Object valueToAdd) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz); final String tableName = AnnotationTools.getTableName(clazz);
final QueryOptions options = new QueryOptions(new OverrideTableName(tableName), final QueryOptions options = new QueryOptions(new OverrideTableName(tableName),
new OptionSpecifyType("id", id.getClass()), new OptionSpecifyType("idOfTheObject", clazzPrimaryKeyValue.getClass()),
new OptionSpecifyType("covers", remoteKey.getClass(), true)); new OptionSpecifyType("filedNameOfTheObject", valueToAdd.getClass(), true));
if (columnId != null && !columnId.equals("id")) { if (clazzPrimaryKeyName == null) {
options.add(new OptionRenameColumn("id", columnId)); clazzPrimaryKeyName = "id";
} }
if (columnList != null && !columnList.equals("covers")) { options.add(new OptionRenameColumn("idOfTheObject", clazzPrimaryKeyName));
options.add(new OptionRenameColumn("covers", columnList)); options.add(new OptionRenameColumn("filedNameOfTheObject", fieldNameToUpdate));
final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, clazzPrimaryKeyValue, options.getAllArray());
if (data.filedNameOfTheObject == null) {
data.filedNameOfTheObject = new ArrayList<>();
} }
final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, id, options.getAllArray()); for (final Object elem : data.filedNameOfTheObject) {
if (data.covers == null) { if (elem.equals(valueToAdd)) {
data.covers = new ArrayList<>();
}
for (final Object elem : data.covers) {
if (elem.equals(remoteKey)) {
return; return;
} }
} }
data.covers.add(remoteKey); data.filedNameOfTheObject.add(valueToAdd);
ioDb.update(data, data.id, List.of("covers"), options.getAllArray()); ioDb.update(data, data.idOfTheObject, List.of("filedNameOfTheObject"), options.getAllArray());
} }
public static void removeLink( public static void removeLink(
final DBAccess ioDb, final DBAccess ioDb,
final Class<?> clazz, final Class<?> clazz,
final String columnId, String clazzPrimaryKeyName,
final Object id, final Object clazzPrimaryKeyValue,
final String columnList, final String fieldNameToUpdate,
final Object remoteKey) throws Exception { final Object valueToRemove) throws Exception {
if (ioDb instanceof final DBAccessSQL daSQL) {
final String tableName = AnnotationTools.getTableName(clazz); final String tableName = AnnotationTools.getTableName(clazz);
final QueryOptions options = new QueryOptions(new OverrideTableName(tableName), final QueryOptions options = new QueryOptions(new OverrideTableName(tableName),
new OptionSpecifyType("id", id.getClass()), new OptionSpecifyType("idOfTheObject", clazzPrimaryKeyValue.getClass()),
new OptionSpecifyType("covers", remoteKey.getClass(), true)); new OptionSpecifyType("filedNameOfTheObject", valueToRemove.getClass(), true));
if (columnId != null && !columnId.equals("id")) { if (clazzPrimaryKeyName == null) {
options.add(new OptionRenameColumn("id", columnId)); clazzPrimaryKeyName = "id";
} }
if (columnList != null && !columnList.equals("covers")) { options.add(new OptionRenameColumn("idOfTheObject", clazzPrimaryKeyName));
options.add(new OptionRenameColumn("covers", columnList)); options.add(new OptionRenameColumn("filedNameOfTheObject", fieldNameToUpdate));
} final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, clazzPrimaryKeyValue, options.getAllArray());
final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, id, options.getAllArray()); if (data.filedNameOfTheObject == null) {
if (data.covers == null) {
return; return;
} }
final List<Object> newList = new ArrayList<>(); final List<Object> newList = new ArrayList<>();
for (final Object elem : data.covers) { for (final Object elem : data.filedNameOfTheObject) {
if (elem.equals(remoteKey)) { if (elem.equals(valueToRemove)) {
continue; continue;
} }
newList.add(elem); newList.add(elem);
} }
data.covers = newList; data.filedNameOfTheObject = newList;
ioDb.update(data, data.id, List.of("covers"), options.getAllArray()); if (data.filedNameOfTheObject.isEmpty()) {
} else if (ioDb instanceof final DBAccessMorphia dam) { data.filedNameOfTheObject = null;
} else {
throw new DataAccessException("DataAccess Not managed");
} }
ioDb.update(data, data.idOfTheObject, List.of("filedNameOfTheObject"), options.getAllArray());
} }
} }

View File

@ -1,7 +1,9 @@
package org.kar.archidata.dataAccess.addOnSQL; package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -9,25 +11,26 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccess;
import org.atriasoft.archidata.dataAccess.DBAccessMorphia;
import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryAnd;
import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.atriasoft.archidata.dataAccess.QueryInList;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.addOnSQL.model.LinkTableGeneric;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.exception.SystemException;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DBAccessMorphia;
import org.kar.archidata.dataAccess.DBAccessSQL;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryAnd;
import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryInList;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.addOnSQL.model.LinkTableGeneric;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.dataAccess.options.OptionSpecifyType;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -86,20 +89,102 @@ public class AddOnManyToMany implements DataAccessAddOn {
return false; return false;
} }
public static String generateLinkTableNameField( public static String hashTo64Chars(final String input) {
try {
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] hash = digest.digest(input.getBytes());
final StringBuilder hexString = new StringBuilder();
for (final byte b : hash) {
final String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString().substring(0, 64);
} catch (final NoSuchAlgorithmException e) {
throw new RuntimeException("Erreur lors du hachage de la chaîne", e);
}
}
public static String hashIfNeeded(final String input) {
if (input.length() > 64) {
// Keep only the 50 first chars
final String truncated = input.substring(0, Math.min(input.length(), 50));
final String fullHash = hashTo64Chars(input);
final String hashPart = fullHash.substring(0, 14);
return truncated + hashPart;
}
return input;
}
public record LinkTableWithMode(
String tableName,
boolean first,
boolean equals) {}
public static LinkTableWithMode generateLinkTableNameField(
final String tableName, final String tableName,
final Field field, final Field field,
final QueryOptions options) throws Exception { final QueryOptions options) throws Exception {
final FieldName name = AnnotationTools.getFieldName(field, options); return generateLinkTableName(tableName, field);
return generateLinkTableName(tableName, name.inTable());
} }
public static String generateLinkTableName(final String tableName, final String name) { public static LinkTableWithMode generateLinkTableName(
String localName = name; final String tableAName,
if (name.endsWith("s")) { final String tableAFieldName,
localName = name.substring(0, name.length() - 1); final String tableBName,
final String tableBFieldName) {
final String concatElementA = tableAName + "_" + tableAFieldName;
final String concatElementB = tableBName + "_" + tableBFieldName;
final int compareResult = concatElementA.compareTo(concatElementB);
if (compareResult == 0) {
return new LinkTableWithMode(hashIfNeeded(concatElementA + "_autolink"), true, true);
} }
return tableName + "_link_" + localName; if (compareResult < 0) {
return new LinkTableWithMode(hashIfNeeded(concatElementA + "_link_" + concatElementB), true, false);
}
return new LinkTableWithMode(hashIfNeeded(concatElementB + "_link_" + concatElementA), false, false);
}
public static LinkTableWithMode generateLinkTableName(
final String tableAName,
final String tableAFieldName,
final ManyToMany manyToMany) throws SystemException {
if (manyToMany == null) {
throw new SystemException("@ManyMany is a null pointer " + tableAName);
}
if (manyToMany.targetEntity() == null) {
throw new SystemException("@ManyMany target entity is a null pointer: " + tableAName);
}
if (manyToMany.mappedBy() == null || manyToMany.mappedBy().isEmpty()) {
throw new SystemException("@ManyMany mapped by is not defined: " + tableAName);
}
final String tableNameRemote = AnnotationTools.getTableName(manyToMany.targetEntity());
return generateLinkTableName(tableAName, tableAFieldName, tableNameRemote, manyToMany.mappedBy());
}
public static LinkTableWithMode generateLinkTableName(final String tableAName, final Field field)
throws SystemException {
if (field == null) {
// TODO: throw !!!!
}
final FieldName columnName = AnnotationTools.getFieldName(field, null);
final ManyToMany manyToMany = AnnotationTools.get(field, ManyToMany.class);
return generateLinkTableName(tableAName, columnName.inTable(), manyToMany);
}
public static LinkTableWithMode generateLinkTableName(final Class<?> clazz, final String fieldName)
throws SystemException {
if (clazz == null) {
throw new SystemException("@ManyMany class reference is a null pointer ");
}
if (fieldName == null || fieldName.isEmpty() || fieldName.isBlank()) {
throw new SystemException("@ManyMany field of class reference is not defined");
}
final String tableName = AnnotationTools.getTableName(clazz);
final Field requestedField = AnnotationTools.getFieldNamed(clazz, fieldName);
return generateLinkTableName(tableName, requestedField);
} }
public void generateConcatQuery( public void generateConcatQuery(
@ -112,18 +197,13 @@ public class AddOnManyToMany implements DataAccessAddOn {
@NotNull final CountInOut count, @NotNull final CountInOut count,
final QueryOptions options) throws Exception { final QueryOptions options) throws Exception {
final ManyToMany manyToMany = AnnotationTools.getManyToMany(field); final ManyToMany manyToMany = AnnotationTools.getManyToMany(field);
String linkTableName = generateLinkTableName(tableName, name); final LinkTableWithMode linkTable = generateLinkTableName(tableName, name, manyToMany);
if (manyToMany.mappedBy() != null && manyToMany.mappedBy().length() != 0) {
// TODO: get the remote table name .....
final String remoteTableName = AnnotationTools.getTableName(manyToMany.targetEntity());
linkTableName = generateLinkTableName(remoteTableName, manyToMany.mappedBy());
}
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0]; .getActualTypeArguments()[0];
final String tmpVariable = "tmp_" + Integer.toString(count.value); final String tmpVariable = "tmp_" + Integer.toString(count.value);
querySelect.append(" (SELECT GROUP_CONCAT("); querySelect.append(" (SELECT GROUP_CONCAT(");
querySelect.append(tmpVariable); querySelect.append(tmpVariable);
if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { if (linkTable.first()) {
querySelect.append(".object2Id "); querySelect.append(".object2Id ");
} else { } else {
querySelect.append(".object1Id "); querySelect.append(".object1Id ");
@ -147,7 +227,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
} }
} }
querySelect.append("') FROM "); querySelect.append("') FROM ");
querySelect.append(linkTableName); querySelect.append(linkTable.tableName());
querySelect.append(" "); querySelect.append(" ");
querySelect.append(tmpVariable); querySelect.append(tmpVariable);
querySelect.append(" WHERE "); querySelect.append(" WHERE ");
@ -160,7 +240,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
querySelect.append(" = "); querySelect.append(" = ");
querySelect.append(tmpVariable); querySelect.append(tmpVariable);
querySelect.append("."); querySelect.append(".");
if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { if (linkTable.first()) {
querySelect.append("object1Id "); querySelect.append("object1Id ");
} else { } else {
querySelect.append("object2Id "); querySelect.append("object2Id ");
@ -168,7 +248,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
if (!"sqlite".equals(ConfigBaseVariable.getDBType())) { if (!"sqlite".equals(ConfigBaseVariable.getDBType())) {
querySelect.append(" GROUP BY "); querySelect.append(" GROUP BY ");
querySelect.append(tmpVariable); querySelect.append(tmpVariable);
if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) { if (linkTable.first()) {
querySelect.append(".object1Id"); querySelect.append(".object1Id");
} else { } else {
querySelect.append(".object2Id"); querySelect.append(".object2Id");
@ -224,8 +304,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
final QueryOptions options, final QueryOptions options,
final List<LazyGetter> lazyCall) throws Exception { 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()); throw new SystemException("@ManyToMany must contain a List");
return;
} }
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0]; .getActualTypeArguments()[0];
@ -234,12 +313,14 @@ public class AddOnManyToMany implements DataAccessAddOn {
field.set(data, idList); field.set(data, idList);
count.inc(); count.inc();
return; return;
} else if (objectClass == UUID.class) { }
if (objectClass == UUID.class) {
final List<UUID> idList = ioDb.getListOfRawUUIDs(rs, count.value); final List<UUID> idList = ioDb.getListOfRawUUIDs(rs, count.value);
field.set(data, idList); field.set(data, idList);
count.inc(); count.inc();
return; return;
} else if (objectClass == ObjectId.class) { }
if (objectClass == ObjectId.class) {
final List<ObjectId> idList = ioDb.getListOfRawOIDs(rs, count.value); final List<ObjectId> idList = ioDb.getListOfRawOIDs(rs, count.value);
field.set(data, idList); field.set(data, idList);
count.inc(); count.inc();
@ -328,6 +409,7 @@ public class AddOnManyToMany implements DataAccessAddOn {
@Override @Override
public void asyncUpdate( public void asyncUpdate(
final DBAccessSQL ioDb, final DBAccessSQL ioDb,
final Object previousData,
final String tableName, final String tableName,
final Object localKey, final Object localKey,
final Field field, final Field field,
@ -345,14 +427,14 @@ public class AddOnManyToMany implements DataAccessAddOn {
"Can not ManyToMany with other than List<Long> or List<UUID> or List<ObjectId> Model: List<" "Can not ManyToMany with other than List<Long> or List<UUID> or List<ObjectId> Model: List<"
+ objectClass.getCanonicalName() + ">"); + objectClass.getCanonicalName() + ">");
} }
final FieldName columnName = AnnotationTools.getFieldName(field, options); final LinkTableWithMode linkTable = generateLinkTableName(tableName, field);
final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); final String obj1 = linkTable.first ? "object1Id" : "object2Id";
final String obj2 = linkTable.first ? "object2Id" : "object1Id";
actions.add(() -> { actions.add(() -> {
ioDb.deleteWhere(LinkTableGeneric.class, new OverrideTableName(linkTableName), ioDb.deleteWhere(LinkTableGeneric.class, new OverrideTableName(linkTable.tableName()),
new Condition(new QueryCondition("object1Id", "=", localKey)), new Condition(new QueryCondition(obj1, "=", localKey)),
new OptionSpecifyType("object1Id", localKey.getClass()), new OptionSpecifyType(obj1, localKey.getClass()), new OptionSpecifyType(obj2, objectClass));
new OptionSpecifyType("object2Id", objectClass));
}); });
asyncInsert(ioDb, tableName, localKey, field, data, actions, options); asyncInsert(ioDb, tableName, localKey, field, data, actions, options);
} }
@ -385,45 +467,47 @@ public class AddOnManyToMany implements DataAccessAddOn {
"Can not ManyToMany with other than List<Long> or List<UUID> or List<ObjectId> Model: List<" "Can not ManyToMany with other than List<Long> or List<UUID> or List<ObjectId> Model: List<"
+ objectClass.getCanonicalName() + ">"); + objectClass.getCanonicalName() + ">");
} }
final FieldName columnName = AnnotationTools.getFieldName(field, options); final LinkTableWithMode linkTable = generateLinkTableName(tableName, field);
final String linkTableName = generateLinkTableName(tableName, columnName.inTable());
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final List<Object> dataCasted = (List<Object>) data; final List<Object> dataCasted = (List<Object>) data;
if (dataCasted.size() == 0) { if (dataCasted.size() == 0) {
return; return;
} }
final String obj1 = linkTable.first ? "object1Id" : "object2Id";
final String obj2 = linkTable.first ? "object2Id" : "object1Id";
final List<LinkTableGeneric> insertElements = new ArrayList<>(); final List<LinkTableGeneric> insertElements = new ArrayList<>();
for (final Object remoteKey : dataCasted) { for (final Object remoteKey : dataCasted) {
if (remoteKey == null) { if (remoteKey == null) {
throw new DataAccessException("Try to insert remote key with null value"); throw new DataAccessException("Try to insert remote key with null value");
} }
if (linkTable.first) {
insertElements.add(new LinkTableGeneric(localKey, remoteKey)); insertElements.add(new LinkTableGeneric(localKey, remoteKey));
} else {
insertElements.add(new LinkTableGeneric(remoteKey, localKey));
}
} }
if (insertElements.size() == 0) { if (insertElements.size() == 0) {
LOGGER.warn("Insert multiple link without any value (may have null in the list): {}", dataCasted); LOGGER.warn("Insert multiple link without any value (may have null in the list): {}", dataCasted);
return; return;
} }
actions.add(() -> { actions.add(() -> {
ioDb.insertMultiple(insertElements, new OverrideTableName(linkTableName), ioDb.insertMultiple(insertElements, new OverrideTableName(linkTable.tableName()),
new OptionSpecifyType("object1Id", localKey.getClass()), new OptionSpecifyType(obj1, localKey.getClass()), new OptionSpecifyType(obj2, objectClass));
new OptionSpecifyType("object2Id", objectClass));
}); });
} }
@Override @Override
public void drop(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options) public void drop(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options)
throws Exception { throws Exception {
final FieldName columnName = AnnotationTools.getFieldName(field, options); final LinkTableWithMode linkTable = generateLinkTableName(tableName, field);
final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); ioDb.drop(LinkTableGeneric.class, new OverrideTableName(linkTable.tableName()));
ioDb.drop(LinkTableGeneric.class, new OverrideTableName(linkTableName));
} }
@Override @Override
public void cleanAll(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options) public void cleanAll(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options)
throws Exception { throws Exception {
final FieldName columnName = AnnotationTools.getFieldName(field, options); final LinkTableWithMode linkTable = generateLinkTableName(tableName, field);
final String linkTableName = generateLinkTableName(tableName, columnName.inTable()); ioDb.cleanAll(LinkTableGeneric.class, new OverrideTableName(linkTable.tableName()));
ioDb.cleanAll(LinkTableGeneric.class, new OverrideTableName(linkTableName));
} }
public static void addLink( public static void addLink(
@ -433,18 +517,19 @@ public class AddOnManyToMany implements DataAccessAddOn {
final String column, final String column,
final Object remoteKey) throws Exception { final Object remoteKey) throws Exception {
if (ioDb instanceof final DBAccessSQL daSQL) { if (ioDb instanceof final DBAccessSQL daSQL) {
final String tableName = AnnotationTools.getTableName(clazz); final LinkTableWithMode linkTable = generateLinkTableName(clazz, column);
final String linkTableName = generateLinkTableName(tableName, column); final LinkTableGeneric insertElement = linkTable.first ? new LinkTableGeneric(localKey, remoteKey)
final LinkTableGeneric insertElement = new LinkTableGeneric(localKey, remoteKey); : new LinkTableGeneric(remoteKey, localKey);
daSQL.insert(insertElement, new OverrideTableName(linkTableName), final String obj1 = linkTable.first ? "object1Id" : "object2Id";
new OptionSpecifyType("object1Id", localKey.getClass()), final String obj2 = linkTable.first ? "object2Id" : "object1Id";
new OptionSpecifyType("object2Id", remoteKey.getClass())); daSQL.insert(insertElement, new OverrideTableName(linkTable.tableName()),
new OptionSpecifyType(obj1, localKey.getClass()),
new OptionSpecifyType(obj2, remoteKey.getClass()));
} else if (ioDb instanceof final DBAccessMorphia dam) { } else if (ioDb instanceof final DBAccessMorphia dam) {
} else { } else {
throw new DataAccessException("DataAccess Not managed"); throw new DataAccessException("DataAccess Not managed");
} }
} }
public static long removeLink( public static long removeLink(
@ -454,13 +539,14 @@ public class AddOnManyToMany implements DataAccessAddOn {
final String column, final String column,
final Object remoteKey) throws Exception { final Object remoteKey) throws Exception {
if (ioDb instanceof final DBAccessSQL daSQL) { if (ioDb instanceof final DBAccessSQL daSQL) {
final String tableName = AnnotationTools.getTableName(clazz); final LinkTableWithMode linkTable = generateLinkTableName(clazz, column);
final String linkTableName = generateLinkTableName(tableName, column); final String obj1 = linkTable.first ? "object1Id" : "object2Id";
return daSQL.deleteWhere(LinkTableGeneric.class, new OverrideTableName(linkTableName), final String obj2 = linkTable.first ? "object2Id" : "object1Id";
new Condition(new QueryAnd(new QueryCondition("object1Id", "=", localKey), return daSQL.deleteWhere(LinkTableGeneric.class, new OverrideTableName(linkTable.tableName()),
new QueryCondition("object2Id", "=", remoteKey))), new Condition(new QueryAnd(new QueryCondition(obj1, "=", localKey),
new OptionSpecifyType("object1Id", localKey.getClass()), new QueryCondition(obj2, "=", remoteKey))),
new OptionSpecifyType("object2Id", remoteKey.getClass())); new OptionSpecifyType(obj1, localKey.getClass()),
new OptionSpecifyType(obj2, remoteKey.getClass()));
} else if (ioDb instanceof final DBAccessMorphia dam) { } else if (ioDb instanceof final DBAccessMorphia dam) {
return 0L; return 0L;
} else { } else {
@ -468,6 +554,8 @@ public class AddOnManyToMany implements DataAccessAddOn {
} }
} }
private static List<String> tableAlreadyCreated = new ArrayList<>();
@Override @Override
public void createTables( public void createTables(
final String tableName, final String tableName,
@ -481,18 +569,21 @@ public class AddOnManyToMany implements DataAccessAddOn {
final int fieldId, final int fieldId,
final QueryOptions options) throws Exception { final QueryOptions options) throws Exception {
final ManyToMany manyToMany = AnnotationTools.getManyToMany(field); final ManyToMany manyToMany = AnnotationTools.getManyToMany(field);
if (manyToMany.mappedBy() != null && manyToMany.mappedBy().length() != 0) { if (manyToMany.mappedBy() == null || manyToMany.mappedBy().length() == 0) {
// not the reference model to create base: throw new SystemException("MappedBy must be set in ManyMany: " + tableName + " " + field.getName());
return;
} }
final String linkTableName = generateLinkTableNameField(tableName, field, options); final LinkTableWithMode linkTable = generateLinkTableNameField(tableName, field, options);
final QueryOptions options2 = new QueryOptions(new OverrideTableName(linkTableName)); if (linkTable.first() || linkTable.equals()) {
final QueryOptions options2 = new QueryOptions(new OverrideTableName(linkTable.tableName()));
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType()) final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0]; .getActualTypeArguments()[0];
final Class<?> primaryType = primaryField.getType(); final Class<?> primaryType = primaryField.getType();
options2.add(new OptionSpecifyType("object1Id", primaryType)); final String obj1 = linkTable.first ? "object1Id" : "object2Id";
options2.add(new OptionSpecifyType("object2Id", objectClass)); final String obj2 = linkTable.first ? "object2Id" : "object1Id";
options2.add(new OptionSpecifyType(obj1, primaryType));
options2.add(new OptionSpecifyType(obj2, objectClass));
final List<String> sqlCommand = DataFactory.createTable(LinkTableGeneric.class, options2); final List<String> sqlCommand = DataFactory.createTable(LinkTableGeneric.class, options2);
postActionList.addAll(sqlCommand); postActionList.addAll(sqlCommand);
} }
}
} }

View File

@ -0,0 +1,464 @@
package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.annotation.ManyToManyLocal;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccess;
import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryInList;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.addOnSQL.model.TableCoversGeneric;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.dataAccess.options.OptionRenameColumn;
import org.atriasoft.archidata.dataAccess.options.OptionSpecifyType;
import org.atriasoft.archidata.dataAccess.options.OverrideTableName;
import org.atriasoft.archidata.exception.SystemException;
import org.atriasoft.archidata.tools.ContextGenericTools;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.constraints.NotNull;
public class AddOnManyToManyLocal implements DataAccessAddOn {
static final Logger LOGGER = LoggerFactory.getLogger(AddOnManyToManyLocal.class);
static final String SEPARATOR_LONG = "-";
static final String SEPARATOR_UUID = "_";
@Override
public Class<?> getAnnotationClass() {
return ManyToManyLocal.class;
}
@Override
public boolean isCompatibleField(final Field field) {
if (field.getType() != List.class) {
return false;
}
final Class<?> objectClass = (Class<?>) ((ParameterizedType) field.getGenericType())
.getActualTypeArguments()[0];
if (objectClass == Long.class || objectClass == UUID.class || objectClass == ObjectId.class) {
return true;
}
final ManyToManyLocal decorators = field.getDeclaredAnnotation(ManyToManyLocal.class);
if (decorators == null) {
return false;
}
if (decorators.targetEntity() == objectClass) {
return true;
}
return false;
}
@Override
public void insertData(
final DBAccessSQL ioDb,
final PreparedStatement ps,
final Field field,
final Object rootObject,
final CountInOut iii)
throws SQLException, IllegalArgumentException, IllegalAccessException, JsonProcessingException {
final Object data = field.get(rootObject);
if (data == null) {
ps.setNull(iii.value, Types.VARCHAR);
}
final ObjectMapper objectMapper = ContextGenericTools.createObjectMapper();
final String dataString = objectMapper.writeValueAsString(data);
ps.setString(iii.value, dataString);
iii.inc();
}
@Override
public boolean isUpdateAsync(final Field field) {
return true;
}
@Override
public void asyncUpdate(
final DBAccessSQL ioDb,
final Object previousData,
final String tableName,
final Object primaryKeyValue,
final Field field,
final Object insertedData,
final List<LazyGetter> actions,
final QueryOptions options) throws Exception {
final Object previousDataValue = field.get(previousData);
Collection<?> previousDataCollection = new ArrayList<>();
if (previousDataValue instanceof final Collection<?> tmpCollection) {
previousDataCollection = tmpCollection;
}
final Object insertedDataValue = insertedData;
Collection<?> insertedDataCollection = new ArrayList<>();
if (insertedDataValue instanceof final Collection<?> tmpCollection) {
insertedDataCollection = tmpCollection;
}
// add new Values
for (final Object value : insertedDataCollection) {
if (previousDataCollection.contains(value)) {
continue;
}
actions.add(() -> {
addLinkRemote(ioDb, field, primaryKeyValue, value);
});
}
// remove old values:
for (final Object value : previousDataCollection) {
if (insertedDataCollection.contains(value)) {
continue;
}
actions.add(() -> {
removeLinkRemote(ioDb, field, primaryKeyValue, value);
});
}
}
/** Some action must be done asynchronously for update or remove element
* @param field
* @return */
@Override
public boolean isInsertAsync(final Field field) throws Exception {
return true;
}
/** 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. */
@Override
public void asyncInsert(
final DBAccessSQL ioDb,
final String tableName,
final Object primaryKeyValue,
final Field field,
final Object data,
final List<LazyGetter> actions,
final QueryOptions options) throws Exception {
final Object insertedData = data;
if (insertedData == null) {
return;
}
if (insertedData instanceof final Collection<?> insertedDataCollection) {
for (final Object value : insertedDataCollection) {
actions.add(() -> {
addLinkRemote(ioDb, field, primaryKeyValue, value);
});
}
}
}
@Override
public boolean isPreviousDataNeeded(final Field field) {
return true;
}
@Override
public boolean canInsert(final Field field) {
return isCompatibleField(field);
}
@Override
public boolean canRetrieve(final Field field) {
return isCompatibleField(field);
}
@Override
public void generateQuery(
@NotNull final String tableName,
@NotNull final String primaryKey,
@NotNull final Field field,
@NotNull final StringBuilder querySelect,
@NotNull final StringBuilder query,
@NotNull final String name,
@NotNull final CountInOut count,
final QueryOptions options) throws Exception {
querySelect.append(" ");
querySelect.append(tableName);
querySelect.append(".");
querySelect.append(name);
count.inc();
}
@Override
public void fillFromQuery(
final DBAccessSQL ioDb,
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) {
throw new SystemException("@ManyToManyLocal must contain a List");
}
final String jsonData = rs.getString(count.value);
count.inc();
if (rs.wasNull()) {
return;
}
final ObjectMapper objectMapper = ContextGenericTools.createObjectMapper();
final ParameterizedType listType = (ParameterizedType) field.getGenericType();
final Class<?> objectClass = (Class<?>) listType.getActualTypeArguments()[0];
if (objectClass == Long.class) {
final List<Long> dataParsed = objectMapper.readValue(jsonData, new TypeReference<List<Long>>() {});
field.set(data, dataParsed);
return;
}
if (objectClass == String.class) {
final List<String> dataParsed = objectMapper.readValue(jsonData, new TypeReference<List<String>>() {});
field.set(data, dataParsed);
return;
}
if (objectClass == UUID.class)
{
final List<UUID> dataParsed = objectMapper.readValue(jsonData, new TypeReference<List<UUID>>() {});
field.set(data, dataParsed);
return;
}
if (objectClass == ObjectId.class) {
final List<ObjectId> dataParsed = objectMapper.readValue(jsonData, new TypeReference<List<ObjectId>>() {});
field.set(data, dataParsed);
return;
}
final ManyToManyLocal decorators = field.getDeclaredAnnotation(ManyToManyLocal.class);
if (decorators == null) {
return;
}
if (objectClass == decorators.targetEntity()) {
final Class<?> foreignKeyType = AnnotationTools.getPrimaryKeyField(objectClass).getType();
if (foreignKeyType == Long.class) {
final List<Long> idList = objectMapper.readValue(jsonData, new TypeReference<List<Long>>() {});
if (idList != null && idList.size() > 0) {
final FieldName idField = AnnotationTools.getFieldName(AnnotationTools.getIdField(objectClass),
options);
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
final LazyGetter lambda = () -> {
// TODO: update to have get with abstract types ....
final Object foreignData = ioDb.getsWhere(decorators.targetEntity(),
new Condition(new QueryInList<>(idField.inTable(), idList)));
if (foreignData == null) {
return;
}
field.set(data, foreignData);
};
lazyCall.add(lambda);
}
} else if (foreignKeyType == UUID.class) {
final List<UUID> idList = objectMapper.readValue(jsonData, new TypeReference<List<UUID>>() {});
if (idList != null && idList.size() > 0) {
final FieldName idField = AnnotationTools.getFieldName(AnnotationTools.getIdField(objectClass),
options);
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
final LazyGetter lambda = () -> {
final List<UUID> childs = new ArrayList<>(idList);
// TODO: update to have get with abstract types ....
final Object foreignData = ioDb.getsWhere(decorators.targetEntity(),
new Condition(new QueryInList<>(idField.inTable(), childs)));
if (foreignData == null) {
return;
}
field.set(data, foreignData);
};
lazyCall.add(lambda);
}
} else if (foreignKeyType == ObjectId.class) {
final List<ObjectId> idList = objectMapper.readValue(jsonData, new TypeReference<List<ObjectId>>() {});
if (idList != null && idList.size() > 0) {
final FieldName idField = AnnotationTools.getFieldName(AnnotationTools.getIdField(objectClass),
options);
// In the lazy mode, the request is done in asynchronous mode, they will be done after...
final LazyGetter lambda = () -> {
final List<ObjectId> childs = new ArrayList<>(idList);
// TODO: update to have get with abstract types ....
final Object foreignData = ioDb.getsWhere(decorators.targetEntity(),
new Condition(new QueryInList<>(idField.inTable(), childs)));
if (foreignData == null) {
return;
}
field.set(data, foreignData);
};
lazyCall.add(lambda);
}
}
}
}
@Override
public void createTables(
final String tableName,
final Field primaryField,
final Field field,
final StringBuilder mainTableBuilder,
final List<String> preActionList,
final List<String> postActionList,
final boolean createIfNotExist,
final boolean createDrop,
final int fieldId,
final QueryOptions options) throws Exception {
// store data as json to response like a no-sql
DataFactory.createTablesSpecificType(tableName, primaryField, field, mainTableBuilder, preActionList,
postActionList, createIfNotExist, createDrop, fieldId, JsonValue.class, options);
}
private static void addLinkLocal(
final DBAccess ioDb,
final Class<?> clazz,
final String clazzPrimaryKeyName,
final Object clazzPrimaryKeyValue,
final String fieldNameToUpdate,
final Object valueToAdd) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz);
final QueryOptions options = new QueryOptions(new OverrideTableName(tableName),
new OptionSpecifyType("idOfTheObject", clazzPrimaryKeyValue.getClass()),
new OptionSpecifyType("filedNameOfTheObject", valueToAdd.getClass(), true));
options.add(new OptionRenameColumn("idOfTheObject", clazzPrimaryKeyName));
options.add(new OptionRenameColumn("filedNameOfTheObject", fieldNameToUpdate));
final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, clazzPrimaryKeyValue, options.getAllArray());
if (data.filedNameOfTheObject == null) {
data.filedNameOfTheObject = new ArrayList<>();
}
for (final Object elem : data.filedNameOfTheObject) {
if (elem.equals(valueToAdd)) {
return;
}
}
data.filedNameOfTheObject.add(valueToAdd);
ioDb.update(data, data.idOfTheObject, List.of("filedNameOfTheObject"), options.getAllArray());
}
public static void addLink(
final DBAccess ioDb,
final Class<?> clazz,
final Object clazzPrimaryKeyValue,
final String fieldNameToUpdate,
final Object valueToAdd) throws Exception {
final Field localField = AnnotationTools.getFieldNamed(clazz, fieldNameToUpdate);
{
//get local field to find the remote field name:
final Field primaryKeyField = AnnotationTools.getPrimaryKeyField(clazz);
final FieldName primaryKeyColomnName = AnnotationTools.getFieldName(primaryKeyField, null);
final FieldName localFieldName = AnnotationTools.getFieldName(localField, null);
addLinkLocal(ioDb, clazz, primaryKeyColomnName.inTable(), clazzPrimaryKeyValue, localFieldName.inTable(),
valueToAdd);
}
addLinkRemote(ioDb, localField, clazzPrimaryKeyValue, valueToAdd);
}
private static void addLinkRemote(
final DBAccess ioDb,
final Field localField,
final Object localPrimaryKeyValue,
final Object remotePrimaryKeyValue) throws Exception {
final ManyToManyLocal manyLocal = AnnotationTools.get(localField, ManyToManyLocal.class);
// Update the remote elements:
if (manyLocal == null || manyLocal.targetEntity() == null || manyLocal.remoteField() == null
|| manyLocal.remoteField().isEmpty()) {
return;
}
{
//get local field to find the remote field name:
final Field primaryKeyField = AnnotationTools.getPrimaryKeyField(manyLocal.targetEntity());
final FieldName primaryKeyColomnName = AnnotationTools.getFieldName(primaryKeyField, null);
final Field remoteField = AnnotationTools.getFieldNamed(manyLocal.targetEntity(), manyLocal.remoteField());
final FieldName localFieldName = AnnotationTools.getFieldName(remoteField, null);
addLinkLocal(ioDb, manyLocal.targetEntity(), primaryKeyColomnName.inTable(), remotePrimaryKeyValue,
localFieldName.inTable(), localPrimaryKeyValue);
}
}
private static void removeLinkLocal(
final DBAccess ioDb,
final Class<?> clazz,
final String clazzPrimaryKeyName,
final Object clazzPrimaryKeyValue,
final String fieldNameToUpdate,
final Object valueToRemove) throws Exception {
final String tableName = AnnotationTools.getTableName(clazz);
final QueryOptions options = new QueryOptions(new OverrideTableName(tableName),
new OptionSpecifyType("idOfTheObject", clazzPrimaryKeyValue.getClass()),
new OptionSpecifyType("filedNameOfTheObject", valueToRemove.getClass(), true));
options.add(new OptionRenameColumn("idOfTheObject", clazzPrimaryKeyName));
options.add(new OptionRenameColumn("filedNameOfTheObject", fieldNameToUpdate));
final TableCoversGeneric data = ioDb.get(TableCoversGeneric.class, clazzPrimaryKeyValue, options.getAllArray());
if (data.filedNameOfTheObject == null) {
return;
}
final List<Object> newList = new ArrayList<>();
for (final Object elem : data.filedNameOfTheObject) {
if (elem.equals(valueToRemove)) {
continue;
}
newList.add(elem);
}
data.filedNameOfTheObject = newList;
if (data.filedNameOfTheObject.isEmpty()) {
data.filedNameOfTheObject = null;
}
ioDb.update(data, data.idOfTheObject, List.of("filedNameOfTheObject"), options.getAllArray());
}
public static void removeLink(
final DBAccess ioDb,
final Class<?> clazz,
final Object clazzPrimaryKeyValue,
final String fieldNameToUpdate,
final Object valueToRemove) throws Exception {
final Field localField = AnnotationTools.getFieldNamed(clazz, fieldNameToUpdate);
{
//get local field to find the remote field name:
final Field primaryKeyField = AnnotationTools.getPrimaryKeyField(clazz);
final FieldName primaryKeyColomnName = AnnotationTools.getFieldName(primaryKeyField, null);
final FieldName localFieldName = AnnotationTools.getFieldName(localField, null);
removeLinkLocal(ioDb, clazz, primaryKeyColomnName.inTable(), clazzPrimaryKeyValue, localFieldName.inTable(),
valueToRemove);
}
removeLinkRemote(ioDb, localField, clazzPrimaryKeyValue, valueToRemove);
}
private static void removeLinkRemote(
final DBAccess ioDb,
final Field localField,
final Object localPrimaryKeyValue,
final Object remotePrimaryKeyValue) throws Exception {
final ManyToManyLocal manyLocal = AnnotationTools.get(localField, ManyToManyLocal.class);
// Update the remote elements:
if (manyLocal == null || manyLocal.targetEntity() == null || manyLocal.remoteField() == null
|| manyLocal.remoteField().isEmpty()) {
return;
}
{
//get local field to find the remote field name:
final Field primaryKeyField = AnnotationTools.getPrimaryKeyField(manyLocal.targetEntity());
final FieldName primaryKeyColomnName = AnnotationTools.getFieldName(primaryKeyField, null);
final Field remoteField = AnnotationTools.getFieldNamed(manyLocal.targetEntity(), manyLocal.remoteField());
final FieldName localFieldName = AnnotationTools.getFieldName(remoteField, null);
removeLinkLocal(ioDb, manyLocal.targetEntity(), primaryKeyColomnName.inTable(), remotePrimaryKeyValue,
localFieldName.inTable(), localPrimaryKeyValue);
}
}
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.addOnSQL; package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -7,16 +7,16 @@ import java.sql.Types;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.UuidUtils;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccessSQL;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.UuidUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.addOnSQL; package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -10,18 +10,18 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.atriasoft.archidata.annotation.AnnotationTools;
import org.atriasoft.archidata.annotation.AnnotationTools.FieldName;
import org.atriasoft.archidata.dataAccess.CountInOut;
import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.atriasoft.archidata.dataAccess.DataFactory;
import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.atriasoft.archidata.dataAccess.QueryCondition;
import org.atriasoft.archidata.dataAccess.QueryOptions;
import org.atriasoft.archidata.dataAccess.options.Condition;
import org.atriasoft.archidata.exception.DataAccessException;
import org.atriasoft.archidata.tools.ConfigBaseVariable;
import org.bson.types.ObjectId; import org.bson.types.ObjectId;
import org.kar.archidata.annotation.AnnotationTools;
import org.kar.archidata.annotation.AnnotationTools.FieldName;
import org.kar.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccessSQL;
import org.kar.archidata.dataAccess.DataFactory;
import org.kar.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryCondition;
import org.kar.archidata.dataAccess.QueryOptions;
import org.kar.archidata.dataAccess.options.Condition;
import org.kar.archidata.exception.DataAccessException;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -231,6 +231,7 @@ public class AddOnOneToMany implements DataAccessAddOn {
final CountInOut count, final CountInOut count,
final QueryOptions options, final QueryOptions options,
final List<LazyGetter> lazyCall) throws Exception { final List<LazyGetter> lazyCall) throws Exception {
try {
if (field.getType() != List.class) { if (field.getType() != List.class) {
LOGGER.error("Can not OneToMany with other than List Model: {}", field.getType().getCanonicalName()); LOGGER.error("Can not OneToMany with other than List Model: {}", field.getType().getCanonicalName());
return; return;
@ -258,32 +259,33 @@ public class AddOnOneToMany implements DataAccessAddOn {
return; return;
} }
if (objectClass == decorators.targetEntity()) { if (objectClass == decorators.targetEntity()) {
final String destinationField = decorators.mappedBy();
final Field typeDestination = AnnotationTools.getFieldNamed(objectClass, destinationField);
final Class<?> destinationClass = typeDestination.getType();
Long parentIdTmp = null; Long parentIdTmp = null;
UUID parendUuidTmp = null; UUID parendUuidTmp = null;
ObjectId parendOidTmp = null; ObjectId parendOidTmp = null;
try { if (destinationClass == Long.class) {
final String modelData = rs.getString(count.value); final String modelData = rs.getString(count.value);
parentIdTmp = Long.valueOf(modelData); parentIdTmp = Long.valueOf(modelData);
count.inc(); count.inc();
} catch (final NumberFormatException ex) { } else if (destinationClass == UUID.class) {
try {
final List<UUID> idList = ioDb.getListOfRawUUIDs(rs, count.value); final List<UUID> idList = ioDb.getListOfRawUUIDs(rs, count.value);
parendUuidTmp = idList.get(0); parendUuidTmp = idList.get(0);
count.inc(); count.inc();
} catch (final NumberFormatException ex2) { } else if (destinationClass == ObjectId.class) {
// TODO : How to manage ObjectId ==> I am not sure it works well...
final List<ObjectId> idList = ioDb.getListOfRawOIDs(rs, count.value); final List<ObjectId> idList = ioDb.getListOfRawOIDs(rs, count.value);
parendOidTmp = idList.get(0); parendOidTmp = idList.get(0);
count.inc(); count.inc();
} }
}
final Long parentId = parentIdTmp; final Long parentId = parentIdTmp;
final UUID parendUuid = parendUuidTmp; final UUID parendUuid = parendUuidTmp;
final ObjectId parendOid = parendOidTmp; final ObjectId parendOid = parendOidTmp;
final String mappingKey = decorators.mappedBy(); final String mappingKey = decorators.mappedBy();
// We get the parent ID ... ==> need to request the list of elements // We get the parent ID ... ==> need to request the list of elements
if (objectClass == Long.class) { if (objectClass == Long.class) {
LOGGER.error("Need to retreive all primary key of all elements"); LOGGER.error("Need to retreive all primary key of all elements.");
//field.set(data, idList); //field.set(data, idList);
return; return;
} else if (objectClass == UUID.class) { } else if (objectClass == UUID.class) {
@ -335,6 +337,10 @@ public class AddOnOneToMany implements DataAccessAddOn {
} }
} }
} }
} catch (final Exception ex) {
ex.printStackTrace();
LOGGER.error("Fail to parse remote {}", ex.getMessage());
}
} }
} }

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.addOnSQL; package org.atriasoft.archidata.dataAccess.addOnSQL;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -6,10 +6,10 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.kar.archidata.dataAccess.CountInOut; import org.atriasoft.archidata.dataAccess.CountInOut;
import org.kar.archidata.dataAccess.DBAccessSQL; import org.atriasoft.archidata.dataAccess.DBAccessSQL;
import org.kar.archidata.dataAccess.LazyGetter; import org.atriasoft.archidata.dataAccess.LazyGetter;
import org.kar.archidata.dataAccess.QueryOptions; import org.atriasoft.archidata.dataAccess.QueryOptions;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -31,10 +31,9 @@ public interface DataAccessAddOn {
boolean isCompatibleField(Field elem); boolean isCompatibleField(Field elem);
/** Insert data in the specific field (the field must be in the current db, otherwiise it does not work at all. /** Insert data in the specific field (the field must be in the current db, otherwiise it does not work at all.
* @param ps DB statement interface. * @param ioDb DB statement interface.
* @param data The date to inject. * @param data The date to inject.
* @param iii The index of injection * @param iii The index of injection
* @return the new index of injection in case of multiple value management
* @throws SQLException */ * @throws SQLException */
void insertData(final DBAccessSQL ioDb, PreparedStatement ps, final Field field, Object data, CountInOut iii) void insertData(final DBAccessSQL ioDb, PreparedStatement ps, final Field field, Object data, CountInOut iii)
throws Exception, SQLException, IllegalArgumentException, IllegalAccessException; throws Exception, SQLException, IllegalArgumentException, IllegalAccessException;
@ -76,9 +75,11 @@ public interface DataAccessAddOn {
/** Create associated table of the specific element. /** Create associated table of the specific element.
* @param tableName * @param tableName
* @param elem * @param primaryField
* @param field
* @param mainTableBuilder * @param mainTableBuilder
* @param ListOtherTables * @param preActionList
* @param postActionList
* @param createIfNotExist * @param createIfNotExist
* @param createDrop * @param createDrop
* @param fieldId * @param fieldId
@ -136,6 +137,7 @@ public interface DataAccessAddOn {
* @param actions Asynchronous action to do after main request. */ * @param actions Asynchronous action to do after main request. */
default void asyncUpdate( default void asyncUpdate(
final DBAccessSQL ioDb, final DBAccessSQL ioDb,
final Object previousData,
final String tableName, final String tableName,
final Object localId, final Object localId,
final Field field, final Field field,
@ -145,6 +147,13 @@ public interface DataAccessAddOn {
} }
/** Some annotation need to collect data before updating the current values
* @param field
* @return */
default boolean isPreviousDataNeeded(final Field field) {
return false;
}
default void drop(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options) default void drop(final DBAccessSQL ioDb, final String tableName, final Field field, final QueryOptions options)
throws Exception { throws Exception {

View File

@ -1,6 +1,6 @@
package org.kar.archidata.dataAccess.addOnSQL.model; package org.atriasoft.archidata.dataAccess.addOnSQL.model;
import org.kar.archidata.model.OIDGenericDataSoftDelete; import org.atriasoft.archidata.model.OIDGenericDataSoftDelete;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column; import jakarta.persistence.Column;

View File

@ -0,0 +1,25 @@
package org.atriasoft.archidata.dataAccess.addOnSQL.model;
import java.util.List;
import org.atriasoft.archidata.annotation.DataJson;
import jakarta.persistence.Id;
public class TableCoversGeneric {
public TableCoversGeneric() {
// nothing to do...
}
public TableCoversGeneric(final Object idOfTheObject, final List<Object> filedNameOfTheObject) {
this.idOfTheObject = idOfTheObject;
this.filedNameOfTheObject = filedNameOfTheObject;
}
@Id
public Object idOfTheObject;
@DataJson()
public List<Object> filedNameOfTheObject;
}

View File

@ -1,4 +1,4 @@
package org.kar.archidata.dataAccess.exportTools; package org.atriasoft.archidata.dataAccess.exportTools;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

Some files were not shown because too many files have changed in this diff Show More