Skip to content
This repository has been archived by the owner on Apr 1, 2022. It is now read-only.

Commit

Permalink
javers#921: Allow JaversAuditableDelete work with id
Browse files Browse the repository at this point in the history
  • Loading branch information
IlyaNerd committed Dec 9, 2019
1 parent 54dd95f commit b7faf6d
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
Expand Up @@ -19,4 +19,9 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface JaversAuditableDelete {
}

/**
* domain type of entity to delete, required in case of delete by id
*/
Class<?> domainType() default Void.class;
}
@@ -1,8 +1,13 @@
package org.javers.spring.auditable.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.javers.common.collections.Maps;
import org.javers.core.Javers;
import org.javers.core.metamodel.type.EntityType;
import org.javers.core.metamodel.type.JaversType;
import org.javers.core.metamodel.type.PrimitiveOrValueType;
import org.javers.spring.annotation.JaversAuditableDelete;
import org.javers.spring.auditable.AspectUtil;
import org.javers.spring.auditable.AuthorProvider;
import org.javers.spring.auditable.CommitPropertiesProvider;
Expand Down Expand Up @@ -30,18 +35,29 @@ public void commitSaveMethodArguments(JoinPoint pjp) {
}
}

public void commitDeleteMethodArguments(JoinPoint pjp) {
for (Object arg : AspectUtil.collectArguments(pjp)) {
commitShallowDelete(arg);
public void commitDeleteMethodArguments(JoinPoint jp) {
for (Object arg : AspectUtil.collectArguments(jp)) {
JaversType typeMapping = javers.getTypeMapping(arg.getClass());
if (typeMapping instanceof EntityType) {
commitShallowDelete(arg);
} else if (typeMapping instanceof PrimitiveOrValueType) {
JaversAuditableDelete javersAuditableDelete =
((MethodSignature) jp.getSignature()).getMethod().getAnnotation(JaversAuditableDelete.class);
Class<?> domainType = javersAuditableDelete.domainType();
if (domainType == Void.class) {
throw new IllegalStateException("Committing by id requires a domain type");
}
commitShallowDeleteById(arg, domainType);
}
}
}

public void commitObject(Object domainObject) {
String author = authorProvider.provide();

javers.commit(author, domainObject, Maps.merge(
commitPropertiesProvider.provideForCommittedObject(domainObject),
commitPropertiesProvider.provide()));
commitPropertiesProvider.provideForCommittedObject(domainObject),
commitPropertiesProvider.provide()));
}

public void commitShallowDelete(Object domainObject) {
Expand Down
Expand Up @@ -27,9 +27,8 @@ protected AbstractSpringAuditableRepositoryAspect(Javers javers, AuthorProvider
}

protected void onSave(JoinPoint pjp, Object returnedObject) {
getRepositoryInterface(pjp).ifPresent( i -> {
AspectUtil.collectReturnedObjects(returnedObject).forEach(o -> javersCommitAdvice.commitObject(o));
});
getRepositoryInterface(pjp).ifPresent(i ->
AspectUtil.collectReturnedObjects(returnedObject).forEach(javersCommitAdvice::commitObject));
}

protected void onDelete(JoinPoint pjp) {
Expand All @@ -56,12 +55,12 @@ private class OnDeleteAuditChangeHandler implements AuditChangeHandler {
public void handle(RepositoryMetadata repositoryMetadata, Object domainObjectOrId) {
if (isIdClass(repositoryMetadata, domainObjectOrId)) {
Class<?> domainType = repositoryMetadata.getDomainType();
if (javers.findSnapshots(QueryBuilder.byInstanceId(domainObjectOrId, domainType).build()).size() == 0) {
if (javers.findSnapshots(QueryBuilder.byInstanceId(domainObjectOrId, domainType).limit(1).build()).size() == 0) {
return;
}
javersCommitAdvice.commitShallowDeleteById(domainObjectOrId, domainType);
} else if (isDomainClass(repositoryMetadata, domainObjectOrId)) {
if (javers.findSnapshots(QueryBuilder.byInstance(domainObjectOrId).build()).size() == 0) {
if (javers.findSnapshots(QueryBuilder.byInstance(domainObjectOrId).limit(1).build()).size() == 0) {
return;
}
javersCommitAdvice.commitShallowDelete(domainObjectOrId);
Expand Down
Expand Up @@ -86,4 +86,50 @@ class JaversAuditableDeleteAspectIntegrationTest extends Specification {
snapshots[1].initial
}
}

def "should commit delete by id when method is annotated with @JaversAuditableDelete"() {
given:
def o = new DummyObject()

when:
repository.save(o)
repository.deleteById(o.id)

then:
def snapshots = javers.findSnapshots(QueryBuilder.byInstanceId(o.id, DummyObject).build())
snapshots.size() == 2
snapshots[0].terminal
snapshots[1].initial
}

def "should commit ids iterable when method is annotated with @JaversAuditableDelete"() {
given:
def objects = [new DummyObject(), new DummyObject()]

when: "iterable arg test"
repository.saveAll(objects)
repository.deleteAllById(objects.collect { it.id })

then:
objects.each {
javers.findSnapshots(QueryBuilder.byInstanceId(it.id, DummyObject).build()).size() == 1

def snapshots = javers.findSnapshots(QueryBuilder.byInstanceId(it.id, DummyObject).build())
snapshots.size() == 2
snapshots[0].terminal
snapshots[1].initial
}
}

def "should throw exception if no domain type present when annotated with @JaversAuditableDelete"() {
given:
def o = new DummyObject()

when:
repository.save(o)
repository.deleteByIdNoClass(o.id)

then:
thrown(IllegalStateException)
}
}
Expand Up @@ -26,7 +26,7 @@ class DummyAuditedRepository {
//... omitted
}

DummyObject find(DummyObject query){
DummyObject find(DummyObject query) {
//... omitted
null
}
Expand All @@ -36,13 +36,26 @@ class DummyAuditedRepository {
//... omitted
}

@JaversAuditableDelete(domainType = DummyObject.class)
void deleteById(String id) {
}

@JaversAuditableDelete(domainType = DummyObject.class)
void deleteAllById(Iterable<String> ids) {
}

@JaversAuditableDelete
void deleteByIdNoClass(String id) {
}


@JaversAuditableDelete
void deleteTwo(DummyObject obj, obj2){
void deleteTwo(DummyObject obj, obj2) {
//... omitted
}

@JaversAuditableDelete
void deleteAll(Iterable<DummyObject> objetcs){
void deleteAll(Iterable<DummyObject> objetcs) {
//... omitted
}

Expand Down

0 comments on commit b7faf6d

Please sign in to comment.