Skip to content

Commit 968c9a1

Browse files
Merge branch 'develop' into renovate/antora-cli-3.x
2 parents 2da8778 + 2553921 commit 968c9a1

File tree

44 files changed

+1680
-35
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1680
-35
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 1.0.10
2+
3+
* Optimistic locking with @Version now possible
4+
15
# 1.0.9
26

37
* Inherited entities with repositories are now realized by reading (finding coherent repositories) and not by writing

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
},
55
"devDependencies": {
66
"@antora/cli": "3.1.9",
7-
"@antora/site-generator": "3.1.8"
7+
"@antora/site-generator": "3.1.9"
88
}
99
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
<plugin>
7676
<groupId>org.apache.maven.plugins</groupId>
7777
<artifactId>maven-pmd-plugin</artifactId>
78-
<version>3.23.0</version>
78+
<version>3.24.0</version>
7979
<configuration>
8080
<includeTests>true</includeTests>
8181
<printFailingErrors>true</printFailingErrors>

spring-data-eclipse-store-demo/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
<plugin>
124124
<groupId>org.apache.maven.plugins</groupId>
125125
<artifactId>maven-surefire-plugin</artifactId>
126-
<version>3.3.0</version>
126+
<version>3.3.1</version>
127127
<configuration>
128128
<argLine>
129129
--add-opens java.base/java.util=ALL-UNNAMED

spring-data-eclipse-store/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@
202202
<plugin>
203203
<groupId>org.apache.maven.plugins</groupId>
204204
<artifactId>maven-project-info-reports-plugin</artifactId>
205-
<version>3.6.1</version>
205+
<version>3.6.2</version>
206206
</plugin>
207207
</plugins>
208208
</pluginManagement>
@@ -269,7 +269,7 @@
269269
<plugin>
270270
<groupId>org.apache.maven.plugins</groupId>
271271
<artifactId>maven-surefire-plugin</artifactId>
272-
<version>3.3.0</version>
272+
<version>3.3.1</version>
273273
<configuration>
274274
<argLine>
275275
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
@@ -393,7 +393,7 @@
393393
<plugin>
394394
<groupId>org.apache.maven.plugins</groupId>
395395
<artifactId>maven-pmd-plugin</artifactId>
396-
<version>3.23.0</version>
396+
<version>3.24.0</version>
397397
<configuration>
398398
<includeTests>true</includeTests>
399399
<printFailingErrors>true</printFailingErrors>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright © 2024 XDEV Software (https://xdev.software)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package software.xdev.spring.data.eclipse.store.exceptions;
17+
18+
public class InvalidVersionException extends RuntimeException
19+
{
20+
public InvalidVersionException(final String message)
21+
{
22+
super(message);
23+
}
24+
}

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/importer/EclipseStoreDataImporter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ private <T> void createRepositoryForType(
263263
storageInstance.getRegistry(),
264264
storageInstance,
265265
storageInstance,
266+
storageInstance,
266267
new SupportedChecker.Implementation(),
267268
storageInstance
268269
),

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/EclipseStoreStorage.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,30 @@
4141
import software.xdev.spring.data.eclipse.store.repository.support.concurrency.ReadWriteLock;
4242
import software.xdev.spring.data.eclipse.store.repository.support.concurrency.ReentrantJavaReadWriteLock;
4343
import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager;
44+
import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManagerProvider;
4445
import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdSetter;
46+
import software.xdev.spring.data.eclipse.store.repository.support.copier.version.EntityVersionIncrementer;
47+
import software.xdev.spring.data.eclipse.store.repository.support.copier.version.VersionManager;
48+
import software.xdev.spring.data.eclipse.store.repository.support.copier.version.VersionManagerProvider;
4549
import software.xdev.spring.data.eclipse.store.repository.support.reposyncer.RepositorySynchronizer;
4650
import software.xdev.spring.data.eclipse.store.repository.support.reposyncer.SimpleRepositorySynchronizer;
4751

4852

4953
public class EclipseStoreStorage
50-
implements EntityListProvider, IdManagerProvider, PersistableChecker, ObjectSwizzling
54+
implements EntityListProvider, IdManagerProvider, VersionManagerProvider, PersistableChecker, ObjectSwizzling
5155
{
5256
private static final Logger LOG = LoggerFactory.getLogger(EclipseStoreStorage.class);
5357
private final Map<Class<?>, SimpleEclipseStoreRepository<?, ?>> entityClassToRepository = new HashMap<>();
58+
/**
59+
* "Why are the IdManagers seperated from the repositories?" - Because there might be entities for which there are
60+
* no repositories, but they still have IDs.
61+
*/
5462
private final Map<Class<?>, IdManager<?, ?>> idManagers = new ConcurrentHashMap<>();
63+
/**
64+
* "Why are the VersionManagers seperated from the repositories?" - Because there might be entities for which there
65+
* are no repositories, but they still have Versions.
66+
*/
67+
private final Map<Class<?>, VersionManager<?>> versionManagers = new ConcurrentHashMap<>();
5568
private final EclipseStoreStorageFoundationProvider foundationProvider;
5669
private EntitySetCollector entitySetCollector;
5770
private PersistableChecker persistenceChecker;
@@ -311,6 +324,7 @@ public synchronized void stop()
311324
this.root = null;
312325
this.registry.reset();
313326
this.idManagers.clear();
327+
this.versionManagers.clear();
314328
LOG.info("Stopped storage.");
315329
}
316330
else
@@ -323,23 +337,37 @@ public synchronized void stop()
323337

324338
@Override
325339
@SuppressWarnings("unchecked")
326-
public <T, ID> IdManager<T, ID> ensureIdManager(final Class<T> domainClass)
340+
public <T, ID> IdManager<T, ID> ensureIdManager(final Class<T> classPossiblyWithId)
327341
{
328342
return (IdManager<T, ID>)this.idManagers.computeIfAbsent(
329-
domainClass,
343+
classPossiblyWithId,
330344
clazz ->
331345
new IdManager<>(
332-
domainClass,
346+
classPossiblyWithId,
333347
(IdSetter<T>)IdSetter.createIdSetter(
334348
clazz,
335-
id -> this.setLastId(clazz, id),
336-
() -> this.getLastId(clazz)
349+
id -> this.setLastId(classPossiblyWithId, id),
350+
() -> this.getLastId(classPossiblyWithId)
337351
),
338352
this
339353
)
340354
);
341355
}
342356

357+
@Override
358+
@SuppressWarnings("unchecked")
359+
public <T> VersionManager<T> ensureVersionManager(final Class<T> possiblyVersionedClass)
360+
{
361+
return (VersionManager<T>)this.versionManagers.computeIfAbsent(
362+
possiblyVersionedClass,
363+
clazz ->
364+
new VersionManager<>(
365+
possiblyVersionedClass,
366+
EntityVersionIncrementer.createVersionSetter(possiblyVersionedClass)
367+
)
368+
);
369+
}
370+
343371
public Object getLastId(final Class<?> entityClass)
344372
{
345373
return this.readWriteLock.read(() -> this.root.getLastId(entityClass));
Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@
1515
*/
1616
package software.xdev.spring.data.eclipse.store.repository.support;
1717

18+
import java.lang.annotation.Annotation;
1819
import java.lang.reflect.Field;
1920
import java.util.Collection;
21+
import java.util.List;
2022
import java.util.Optional;
2123

2224
import software.xdev.spring.data.eclipse.store.repository.access.AccessHelper;
2325

2426

25-
public final class IdFieldFinder
27+
public final class AnnotatedFieldFinder
2628
{
27-
private IdFieldFinder()
29+
private AnnotatedFieldFinder()
2830
{
2931
}
3032

@@ -35,16 +37,45 @@ private IdFieldFinder()
3537
* @return field with ID-Annotation. Is {@link Optional#empty()} if no field was found.
3638
*/
3739
public static Optional<Field> findIdField(final Class<?> domainClass)
40+
{
41+
return findAnnotatedField(
42+
domainClass,
43+
List.of(jakarta.persistence.Id.class, org.springframework.data.annotation.Id.class)
44+
);
45+
}
46+
47+
/**
48+
* Finds any field in a class with an Version-Annotation ({@link jakarta.persistence.Version} or
49+
* {@link org.springframework.data.annotation.Version}). Finds this field recursively in the Hierarchy-tree.
50+
*
51+
* @return field with Version-Annotation. Is {@link Optional#empty()} if no field was found.
52+
*/
53+
public static Optional<Field> findVersionField(final Class<?> domainClass)
54+
{
55+
return findAnnotatedField(
56+
domainClass,
57+
List.of(jakarta.persistence.Version.class, org.springframework.data.annotation.Version.class)
58+
);
59+
}
60+
61+
/**
62+
* Finds any field in a class with specified annotations. Finds this field recursively in the Hierarchy-tree.
63+
*
64+
* @return field with annotation. Is {@link Optional#empty()} if no field was found.
65+
*/
66+
public static Optional<Field> findAnnotatedField(
67+
final Class<?> domainClass,
68+
final Collection<Class<? extends Annotation>> annotations)
3869
{
3970
final Collection<Field> classFields = AccessHelper.getInheritedPrivateFieldsByName(domainClass).values();
4071
for(final Field currentField : classFields)
4172
{
42-
if(
43-
currentField.getAnnotationsByType(jakarta.persistence.Id.class).length > 0
44-
|| currentField.getAnnotationsByType(org.springframework.data.annotation.Id.class).length > 0
45-
)
73+
for(final Class<? extends Annotation> annotation : annotations)
4674
{
47-
return Optional.of(currentField);
75+
if(currentField.getAnnotationsByType(annotation).length > 0)
76+
{
77+
return Optional.of(currentField);
78+
}
4879
}
4980
}
5081
return Optional.empty();

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/EclipseStoreRepositoryFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ private <T> WorkingCopier<T> createWorkingCopier(
7979
storage.getRegistry(),
8080
storage,
8181
storage,
82+
storage,
8283
new SupportedChecker.Implementation(),
8384
storage
8485
);

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManager.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,26 @@
2828
import software.xdev.spring.data.eclipse.store.exceptions.NoIdFieldFoundException;
2929
import software.xdev.spring.data.eclipse.store.repository.EclipseStoreStorage;
3030
import software.xdev.spring.data.eclipse.store.repository.access.modifier.FieldAccessModifier;
31-
import software.xdev.spring.data.eclipse.store.repository.support.IdFieldFinder;
31+
import software.xdev.spring.data.eclipse.store.repository.support.AnnotatedFieldFinder;
3232

3333

3434
public class IdManager<T, ID> implements EntityGetterById<T, ID>, IdGetter<T, ID>
3535
{
36-
private final Class<T> domainClass;
36+
private final Class<T> classWithId;
3737
private final IdSetter<T> idSetter;
3838
private final Optional<Field> idField;
3939
private final EclipseStoreStorage storage;
4040

4141
public IdManager(
42-
final Class<T> domainClass,
42+
final Class<T> classWithId,
4343
final IdSetter<T> idSetter,
4444
final EclipseStoreStorage storage
4545
)
4646
{
47-
this.domainClass = domainClass;
47+
this.classWithId = classWithId;
4848
this.idSetter = idSetter;
4949
this.storage = storage;
50-
this.idField = IdFieldFinder.findIdField(this.domainClass);
50+
this.idField = AnnotatedFieldFinder.findIdField(this.classWithId);
5151
}
5252

5353
public Field ensureIdField()
@@ -56,7 +56,7 @@ public Field ensureIdField()
5656
{
5757
throw new NoIdFieldFoundException(String.format(
5858
"Could not find id field in class %s",
59-
this.domainClass.getSimpleName()));
59+
this.classWithId.getSimpleName()));
6060
}
6161
return this.idField.get();
6262
}
@@ -67,7 +67,7 @@ public Optional<T> findById(@Nonnull final ID id)
6767
this.ensureIdField();
6868
return (Optional<T>)this.storage.getReadWriteLock().read(
6969
() -> this.storage
70-
.getEntityProvider(this.domainClass)
70+
.getEntityProvider(this.classWithId)
7171
.stream()
7272
.filter(entity -> id.equals(this.getId(entity)))
7373
.findAny()
@@ -79,7 +79,7 @@ public List<T> findAllById(@Nonnull final Iterable<ID> idsToFind)
7979
this.ensureIdField();
8080
return (List<T>)this.storage.getReadWriteLock().read(
8181
() -> this.storage
82-
.getEntityProvider(this.domainClass)
82+
.getEntityProvider(this.classWithId)
8383
.stream()
8484
.filter(
8585
entity ->

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/IdManagerProvider.java renamed to spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdManagerProvider.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package software.xdev.spring.data.eclipse.store.repository;
17-
18-
import software.xdev.spring.data.eclipse.store.repository.support.copier.id.IdManager;
19-
16+
package software.xdev.spring.data.eclipse.store.repository.support.copier.id;
2017

2118
public interface IdManagerProvider
2219
{

spring-data-eclipse-store/src/main/java/software/xdev/spring/data/eclipse/store/repository/support/copier/id/IdSetter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import jakarta.persistence.GeneratedValue;
2525

26-
import software.xdev.spring.data.eclipse.store.repository.support.IdFieldFinder;
26+
import software.xdev.spring.data.eclipse.store.repository.support.AnnotatedFieldFinder;
2727
import software.xdev.spring.data.eclipse.store.repository.support.copier.id.strategy.IdFinder;
2828

2929

@@ -41,7 +41,7 @@ static <T> IdSetter<T> createIdSetter(
4141
Objects.requireNonNull(classWithId);
4242
Objects.requireNonNull(lastIdPersister);
4343
Objects.requireNonNull(lastIdGetter);
44-
final Optional<Field> idField = IdFieldFinder.findIdField(classWithId);
44+
final Optional<Field> idField = AnnotatedFieldFinder.findIdField(classWithId);
4545
if(idField.isEmpty())
4646
{
4747
return new NotSettingIdSetter<>();

0 commit comments

Comments
 (0)