Skip to content

Commit 18fc11b

Browse files
authored
Merge pull request #19 from kaiso/support/feature/#14
Support/feature/#14
2 parents 32e8658 + 0cf046c commit 18fc11b

19 files changed

Lines changed: 489 additions & 238 deletions

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>io.github.kaiso.relmongo</groupId>
77
<artifactId>relmongo</artifactId>
8-
<version>1.1.0</version>
8+
<version>1.2.0</version>
99
<packaging>jar</packaging>
1010

1111
<name>relmongo</name>

src/main/java/io/github/kaiso/relmongo/annotation/CascadeType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public enum CascadeType {
2525
*/
2626
PERSIST,
2727

28+
/**
29+
* Cascade remove operation
30+
*/
31+
REMOVE,
32+
2833
/**
2934
* Cascade ALL operations
3035
*/

src/main/java/io/github/kaiso/relmongo/events/callback/PersistentPropertyCascadingCallback.java

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Copyright 2018 Kais OMRI [kais.omri.int@gmail.com] and authors.
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+
17+
package io.github.kaiso.relmongo.events.callback;
18+
19+
import com.mongodb.DBObject;
20+
21+
import io.github.kaiso.relmongo.annotation.CascadeType;
22+
import io.github.kaiso.relmongo.annotation.OneToMany;
23+
import io.github.kaiso.relmongo.annotation.OneToOne;
24+
import io.github.kaiso.relmongo.mongo.DatabaseOperations;
25+
26+
import org.bson.types.ObjectId;
27+
import org.springframework.data.mongodb.core.MongoOperations;
28+
import org.springframework.util.ReflectionUtils;
29+
import org.springframework.util.ReflectionUtils.FieldCallback;
30+
31+
import java.lang.reflect.Field;
32+
import java.util.Arrays;
33+
import java.util.Collection;
34+
35+
public class PersistentPropertyCascadingRemoveCallback implements FieldCallback {
36+
37+
private DBObject source;
38+
private MongoOperations mongoOperations;
39+
private ObjectId id;
40+
private Object entity;
41+
42+
public PersistentPropertyCascadingRemoveCallback(DBObject source, MongoOperations mongoOperations, Class<?> clazz) {
43+
super();
44+
this.source = source;
45+
this.mongoOperations = mongoOperations;
46+
this.id = (ObjectId) this.source.get("_id");
47+
if (this.id != null) {
48+
Collection<?> findByIds = DatabaseOperations.findByIds(mongoOperations, clazz, id);
49+
this.entity = findByIds != null && !findByIds.isEmpty() ? findByIds.iterator().next() : null;
50+
}
51+
}
52+
53+
public void doWith(Field field) throws IllegalAccessException {
54+
ReflectionUtils.makeAccessible(field);
55+
if (field.isAnnotationPresent(OneToMany.class)) {
56+
doCascade(field, field.getAnnotation(OneToMany.class).cascade());
57+
} else if (field.isAnnotationPresent(OneToOne.class)) {
58+
doCascade(field, field.getAnnotation(OneToOne.class).cascade());
59+
}
60+
61+
}
62+
63+
private void doCascade(Field field, CascadeType cascadeType) throws IllegalAccessException {
64+
Object child = field.get(entity);
65+
if (child != null) {
66+
if (Collection.class.isAssignableFrom(child.getClass())) {
67+
cascadeCollection(cascadeType, (Collection<?>) child);
68+
69+
} else {
70+
cascadeItem(cascadeType, child);
71+
72+
}
73+
}
74+
75+
}
76+
77+
private void cascadeItem(CascadeType cascadeType, Object child) {
78+
if (Arrays.asList(CascadeType.REMOVE, CascadeType.ALL).contains(cascadeType)) {
79+
mongoOperations.remove(child);
80+
}
81+
}
82+
83+
private void cascadeCollection(CascadeType cascadeType, Collection<?> child) {
84+
if (Arrays.asList(CascadeType.REMOVE, CascadeType.ALL).contains(cascadeType)) {
85+
child.parallelStream().forEach(mongoOperations::remove);
86+
}
87+
}
88+
89+
public void doProcessing() {
90+
if (id == null || entity == null) {
91+
return;
92+
}
93+
ReflectionUtils.doWithFields(entity.getClass(), this);
94+
}
95+
96+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* Copyright 2018 Kais OMRI [kais.omri.int@gmail.com] and authors.
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+
17+
package io.github.kaiso.relmongo.events.callback;
18+
19+
import io.github.kaiso.relmongo.annotation.CascadeType;
20+
import io.github.kaiso.relmongo.annotation.OneToMany;
21+
import io.github.kaiso.relmongo.annotation.OneToOne;
22+
23+
import org.springframework.data.mongodb.core.MongoOperations;
24+
import org.springframework.util.ReflectionUtils;
25+
import org.springframework.util.ReflectionUtils.FieldCallback;
26+
27+
import java.lang.reflect.Field;
28+
import java.util.Arrays;
29+
import java.util.Collection;
30+
31+
public class PersistentPropertyCascadingSaveCallback implements FieldCallback {
32+
33+
private Object source;
34+
private MongoOperations mongoOperations;
35+
36+
public PersistentPropertyCascadingSaveCallback(Object source, MongoOperations mongoOperations) {
37+
super();
38+
this.source = source;
39+
this.mongoOperations = mongoOperations;
40+
}
41+
42+
public void doWith(Field field) throws IllegalAccessException {
43+
ReflectionUtils.makeAccessible(field);
44+
if (field.isAnnotationPresent(OneToMany.class)) {
45+
doCascade(field, field.getAnnotation(OneToMany.class).cascade());
46+
} else if (field.isAnnotationPresent(OneToOne.class)) {
47+
doCascade(field, field.getAnnotation(OneToOne.class).cascade());
48+
}
49+
50+
}
51+
52+
private void doCascade(Field field, CascadeType cascadeType) throws IllegalAccessException {
53+
Object child = field.get(source);
54+
if (child != null) {
55+
if (Collection.class.isAssignableFrom(child.getClass())) {
56+
cascadeCollection(cascadeType, (Collection<?>) child);
57+
58+
} else {
59+
cascadeItem(cascadeType, child);
60+
61+
}
62+
}
63+
64+
}
65+
66+
private void cascadeItem(CascadeType cascadeType, Object child) {
67+
if (Arrays.asList(CascadeType.PERSIST, CascadeType.ALL).contains(cascadeType)) {
68+
mongoOperations.save(child);
69+
}
70+
}
71+
72+
private void cascadeCollection(CascadeType cascadeType, Collection<?> child) {
73+
if (Arrays.asList(CascadeType.PERSIST, CascadeType.ALL).contains(cascadeType)) {
74+
child.parallelStream().forEach(mongoOperations::save);
75+
}
76+
}
77+
78+
}

src/main/java/io/github/kaiso/relmongo/events/callback/PersistentPropertyLazyLoadingCallback.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,71 @@
1616

1717
package io.github.kaiso.relmongo.events.callback;
1818

19+
import com.mongodb.DBObject;
20+
1921
import io.github.kaiso.relmongo.annotation.FetchType;
2022
import io.github.kaiso.relmongo.annotation.JoinProperty;
2123
import io.github.kaiso.relmongo.annotation.OneToMany;
2224
import io.github.kaiso.relmongo.annotation.OneToOne;
25+
import io.github.kaiso.relmongo.exception.RelMongoConfigurationException;
26+
import io.github.kaiso.relmongo.mongo.DocumentUtils;
2327
import io.github.kaiso.relmongo.mongo.PersistentRelationResolver;
28+
import io.github.kaiso.relmongo.util.ReflectionsUtil;
2429

2530
import org.springframework.data.mongodb.core.MongoOperations;
2631
import org.springframework.util.ReflectionUtils;
2732
import org.springframework.util.ReflectionUtils.FieldCallback;
2833

2934
import java.lang.reflect.Field;
35+
import java.util.ArrayList;
3036
import java.util.Collection;
37+
import java.util.List;
38+
import java.util.stream.Collectors;
3139

3240
public class PersistentPropertyLazyLoadingCallback implements FieldCallback {
3341

3442
private Object source;
3543
private MongoOperations mongoOperations;
44+
private DBObject document;
3645

37-
public PersistentPropertyLazyLoadingCallback(Object source, MongoOperations mongoOperations) {
46+
public PersistentPropertyLazyLoadingCallback(Object source, DBObject document, MongoOperations mongoOperations) {
3847
super();
3948
this.source = source;
4049
this.mongoOperations = mongoOperations;
50+
this.document = document;
4151
}
4252

4353
public void doWith(Field field) throws IllegalAccessException {
4454
ReflectionUtils.makeAccessible(field);
4555

56+
if (DocumentUtils.isLoaded(document.get(field.getName()))) {
57+
return;
58+
}
59+
4660
if ((field.isAnnotationPresent(OneToMany.class) && FetchType.LAZY.equals(field.getAnnotation(OneToMany.class).fetch()))
4761
|| (field.isAnnotationPresent(OneToOne.class) && FetchType.LAZY.equals(field.getAnnotation(OneToOne.class).fetch()))) {
62+
String joinPropertyName;
4863
try {
49-
field.getAnnotation(JoinProperty.class).name();
64+
joinPropertyName = field.getAnnotation(JoinProperty.class).name();
5065
} catch (Exception e) {
51-
throw new IllegalArgumentException("Missing or misconfigured @JoinProperty annotation", e);
66+
throw new RelMongoConfigurationException("Missing or misconfigured @JoinProperty annotation", e);
5267
}
5368
if (field.isAnnotationPresent(OneToMany.class) && !Collection.class.isAssignableFrom(field.getType())) {
54-
throw new IllegalArgumentException("in @OneToMany, the field must be of type collection ");
69+
throw new RelMongoConfigurationException("in @OneToMany, the field must be of type collection ");
70+
}
71+
72+
Object relations = document.get(joinPropertyName);
73+
List<Object> identifierList = new ArrayList<>();
74+
if (relations == null) {
75+
return;
76+
}
77+
if (relations instanceof Collection) {
78+
identifierList.addAll(((Collection<?>) relations).stream().map(DocumentUtils::mapIdentifier).collect(Collectors.toList()));
79+
} else {
80+
identifierList.add(DocumentUtils.mapIdentifier(relations));
5581
}
56-
field.set(source, PersistentRelationResolver.lazyLoader(field.getType(), field.get(source), mongoOperations));
82+
field.set(source, PersistentRelationResolver.lazyLoader(field.getType(), mongoOperations, identifierList, ReflectionsUtil.getGenericType(field),
83+
field.get(source)));
5784

5885
}
5986

src/main/java/io/github/kaiso/relmongo/events/callback/PersistentPropertyLoadingCallback.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
import io.github.kaiso.relmongo.annotation.JoinProperty;
2424
import io.github.kaiso.relmongo.annotation.OneToMany;
2525
import io.github.kaiso.relmongo.annotation.OneToOne;
26+
import io.github.kaiso.relmongo.exception.RelMongoConfigurationException;
2627
import io.github.kaiso.relmongo.model.LoadableObjectsMetadata;
28+
import io.github.kaiso.relmongo.mongo.DocumentUtils;
2729
import io.github.kaiso.relmongo.util.ReflectionsUtil;
2830

2931
import org.springframework.util.ReflectionUtils;
@@ -65,15 +67,21 @@ private void loadAssociation(Field field, FetchType fetchType, Class<?> annotati
6567
}
6668
Object ids = null;
6769
try {
70+
6871
ids = ((BasicDBObject) source).get(name);
72+
73+
if (DocumentUtils.isLoaded(((BasicDBObject) source).get(field.getName())) || ids == null) {
74+
return;
75+
}
76+
6977
if (OneToOne.class.equals(annotation) && ids instanceof BasicDBList) {
7078
// mongo database lookups return always an array if unwind is not used event if
7179
// it is a one ot one association
7280
BasicDBList list = (BasicDBList) ids;
7381
ids = list.isEmpty() ? list : list.get(0);
7482
}
7583
} catch (Exception e) {
76-
throw new IllegalArgumentException("Property defined in @JoinProperty annotation is not present", e);
84+
throw new RelMongoConfigurationException("Property defined in @JoinProperty annotation is not present", e);
7785
}
7886

7987
loadableObjects.add(new LoadableObjectsMetadata(field.getName(), name, "_id", ReflectionsUtil.getGenericType(field), fetchType, ids));

0 commit comments

Comments
 (0)