Skip to content

Commit a8d7f0a

Browse files
authored
Merge pull request #3 from kaiso/feature/#1
[US#1] implement @OnetoOne association
2 parents 44905c3 + 708540b commit a8d7f0a

23 files changed

Lines changed: 700 additions & 310 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.0.0-alpha</version>
8+
<version>1.0.0-beta</version>
99
<packaging>jar</packaging>
1010

1111
<name>relmongo</name>

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

Lines changed: 0 additions & 80 deletions
This file was deleted.

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,4 @@
2626
@Target(ElementType.FIELD)
2727
public @interface JoinProperty {
2828
String name() default "";
29-
String referencedPropertyName() default "_id";
3029
}

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

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

2424

2525
/**
26-
* Describes Unidirectional OneToMany relation
26+
* Describes Unidirectional OneToMany relation <br>
27+
* The referenced property for this association in the target object is allways the "_id"
2728
*
2829
*/
2930
@Retention(RetentionPolicy.RUNTIME)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Copyright 2018 Kais OMRI 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.annotation;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
/**
25+
* Describes Unidirectional OneToOne relation
26+
* The referenced property for this association in the target object is allways the "_id"
27+
*
28+
*/
29+
@Retention(RetentionPolicy.RUNTIME)
30+
@Target(ElementType.FIELD)
31+
public @interface OneToOne {
32+
FetchType fetch() default FetchType.LAZY;
33+
}

src/main/java/io/github/kaiso/relmongo/config/PersistenceConfiguration.java

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

1818
package io.github.kaiso.relmongo.config;
1919

20-
import io.github.kaiso.relmongo.MongoEventListener;
20+
import io.github.kaiso.relmongo.events.listener.MongoEventListener;
2121

2222
import org.springframework.context.annotation.Bean;
2323
import org.springframework.context.annotation.Configuration;

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.github.kaiso.relmongo;
17+
package io.github.kaiso.relmongo.events.callback;
1818

1919
import io.github.kaiso.relmongo.annotation.FetchType;
2020
import io.github.kaiso.relmongo.annotation.JoinProperty;
2121
import io.github.kaiso.relmongo.annotation.OneToMany;
22+
import io.github.kaiso.relmongo.annotation.OneToOne;
23+
import io.github.kaiso.relmongo.mongo.PersistentRelationResolver;
2224

2325
import org.springframework.data.mongodb.core.MongoOperations;
2426
import org.springframework.util.ReflectionUtils;
@@ -41,21 +43,17 @@ public PersistentPropertyLazyLoadingCallback(Object source, MongoOperations mong
4143
public void doWith(Field field) throws IllegalAccessException {
4244
ReflectionUtils.makeAccessible(field);
4345

44-
if (field.isAnnotationPresent(OneToMany.class)&& FetchType.LAZY.equals(field.getAnnotation(OneToMany.class).fetch())) {
45-
String referencedPropertyName = "";
46+
if ((field.isAnnotationPresent(OneToMany.class) && FetchType.LAZY.equals(field.getAnnotation(OneToMany.class).fetch()))
47+
|| (field.isAnnotationPresent(OneToOne.class) && FetchType.LAZY.equals(field.getAnnotation(OneToOne.class).fetch()))) {
4648
try {
47-
referencedPropertyName = field.getAnnotation(JoinProperty.class).referencedPropertyName();
49+
field.getAnnotation(JoinProperty.class).name();
4850
} catch (Exception e) {
4951
throw new IllegalArgumentException("Missing or misconfigured @JoinProperty annotation", e);
5052
}
51-
if (!"_id".equals(referencedPropertyName)) {
52-
throw new IllegalArgumentException("in @OneToMany, referencedPropertyName must be allways _id ");
53+
if (field.isAnnotationPresent(OneToMany.class) && !Collection.class.isAssignableFrom(field.getType())) {
54+
throw new IllegalArgumentException("in @OneToMany, the field must be of type collection ");
5355
}
54-
if (!Collection.class.isAssignableFrom(field.getType())) {
55-
throw new IllegalArgumentException("in @OneToMany, the field must be of type collection ");
56-
}
57-
58-
field.set(source, PersistentRelationResolver.lazyLoader(field.getType(), field.get(source), mongoOperations));
56+
field.set(source, PersistentRelationResolver.lazyLoader(field.getType(), field.get(source), mongoOperations));
5957

6058
}
6159

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* Copyright 2018 Kais OMRI 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.BasicDBObject;
20+
21+
import io.github.kaiso.relmongo.annotation.FetchType;
22+
import io.github.kaiso.relmongo.annotation.JoinProperty;
23+
import io.github.kaiso.relmongo.annotation.OneToMany;
24+
import io.github.kaiso.relmongo.annotation.OneToOne;
25+
import io.github.kaiso.relmongo.model.LoadableObjectsMetadata;
26+
import io.github.kaiso.relmongo.util.ReflectionsUtil;
27+
28+
import org.springframework.util.ReflectionUtils;
29+
import org.springframework.util.ReflectionUtils.FieldCallback;
30+
31+
import java.lang.reflect.Field;
32+
import java.util.ArrayList;
33+
import java.util.List;
34+
35+
public class PersistentPropertyLoadingCallback implements FieldCallback {
36+
37+
private List<LoadableObjectsMetadata> loadableObjects = new ArrayList<>();
38+
private Object source;
39+
40+
public PersistentPropertyLoadingCallback(Object source) {
41+
super();
42+
this.source = source;
43+
}
44+
45+
public void doWith(Field field) throws IllegalAccessException {
46+
ReflectionUtils.makeAccessible(field);
47+
FetchType fetchType = null;
48+
if (field.isAnnotationPresent(OneToMany.class)) {
49+
fetchType = field.getAnnotation(OneToMany.class).fetch();
50+
loadAssociation(field, fetchType);
51+
} else if (field.isAnnotationPresent(OneToOne.class)) {
52+
fetchType = field.getAnnotation(OneToOne.class).fetch();
53+
loadAssociation(field, fetchType);
54+
}
55+
56+
}
57+
58+
private void loadAssociation(Field field, FetchType fetchType) {
59+
String name = "";
60+
try {
61+
name = field.getAnnotation(JoinProperty.class).name();
62+
} catch (Exception e) {
63+
throw new IllegalArgumentException("Missing or misconfigured @JoinProperty annotation", e);
64+
}
65+
Object ids = null;
66+
try {
67+
ids = ((BasicDBObject) source).get(name);
68+
} catch (Exception e) {
69+
throw new IllegalArgumentException("Property defined in @JoinProperty annotation is not present", e);
70+
}
71+
72+
loadableObjects.add(new LoadableObjectsMetadata(field.getName(), name, "_id", ReflectionsUtil.getGenericType(field), fetchType, ids));
73+
}
74+
75+
public List<LoadableObjectsMetadata> getLoadableObjects() {
76+
return loadableObjects;
77+
}
78+
79+
}

src/main/java/io/github/kaiso/relmongo/PersistentPropertySavingCallback.java renamed to src/main/java/io/github/kaiso/relmongo/events/callback/PersistentPropertySavingCallback.java

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.github.kaiso.relmongo;
17+
package io.github.kaiso.relmongo.events.callback;
1818

1919
import com.mongodb.BasicDBList;
2020
import com.mongodb.BasicDBObject;
2121
import com.mongodb.DBObject;
2222

2323
import io.github.kaiso.relmongo.annotation.JoinProperty;
2424
import io.github.kaiso.relmongo.annotation.OneToMany;
25+
import io.github.kaiso.relmongo.annotation.OneToOne;
2526

2627
import org.springframework.util.ReflectionUtils;
2728
import org.springframework.util.ReflectionUtils.FieldCallback;
@@ -40,33 +41,34 @@ public PersistentPropertySavingCallback(Object source) {
4041

4142
public void doWith(Field field) throws IllegalAccessException {
4243
ReflectionUtils.makeAccessible(field);
44+
if (field.isAnnotationPresent(OneToMany.class) || field.isAnnotationPresent(OneToOne.class)) {
45+
saveAssociation(field);
46+
}
4347

44-
if (field.isAnnotationPresent(OneToMany.class)) {
45-
String name = "";
46-
String referencedPropertyName = "";
47-
try {
48-
name = field.getAnnotation(JoinProperty.class).name();
49-
referencedPropertyName = field.getAnnotation(JoinProperty.class).referencedPropertyName();
50-
} catch (Exception e) {
51-
throw new IllegalArgumentException("Missing or misconfigured @JoinProperty annotation", e);
52-
}
53-
if (!"_id".equals(referencedPropertyName)) {
54-
throw new IllegalArgumentException("in @OneToMany, referencedPropertyName must be allways _id ");
55-
}
56-
Object ids = null;
57-
try {
58-
ids = ((BasicDBObject) source).get(name);
59-
if (ids instanceof BasicDBList) {
60-
BasicDBList list = new BasicDBList();
61-
list.addAll(((BasicDBList) ids).stream().map(this::keepOnlyIdentifier).collect(Collectors.toList()));
62-
((BasicDBObject) source).put(name,list);
63-
}
64-
} catch (Exception e) {
65-
throw new IllegalArgumentException("Property defined in @JoinProperty annotation is not present", e);
66-
}
48+
}
6749

50+
private void saveAssociation(Field field) {
51+
String name = "";
52+
try {
53+
name = field.getAnnotation(JoinProperty.class).name();
54+
} catch (Exception e) {
55+
throw new IllegalArgumentException("Missing or misconfigured @JoinProperty annotation", e);
56+
}
57+
Object reference = null;
58+
try {
59+
reference = ((BasicDBObject) source).get(field.getName());
60+
if (reference instanceof BasicDBList) {
61+
BasicDBList list = new BasicDBList();
62+
list.addAll(((BasicDBList) reference).stream().map(this::keepOnlyIdentifier).collect(Collectors.toList()));
63+
((BasicDBObject) source).remove(field.getName());
64+
((BasicDBObject) source).put(name, list);
65+
} else if (reference instanceof BasicDBObject) {
66+
((BasicDBObject) source).remove(field.getName());
67+
((BasicDBObject) source).put(name, ((BasicDBObject) reference).get("_id"));
68+
}
69+
} catch (Exception e) {
70+
throw new IllegalArgumentException("Property defined in @JoinProperty annotation is not present", e);
6871
}
69-
7072
}
7173

7274
private BasicDBObject keepOnlyIdentifier(Object obj) {

src/main/java/io/github/kaiso/relmongo/MongoEventListener.java renamed to src/main/java/io/github/kaiso/relmongo/events/listener/MongoEventListener.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
* limitations under the License.
1515
*/
1616

17-
package io.github.kaiso.relmongo;
17+
package io.github.kaiso.relmongo.events.listener;
1818

19-
import io.github.kaiso.relmongo.annotation.FetchType;
19+
import io.github.kaiso.relmongo.events.callback.PersistentPropertyLazyLoadingCallback;
20+
import io.github.kaiso.relmongo.events.callback.PersistentPropertyLoadingCallback;
21+
import io.github.kaiso.relmongo.events.callback.PersistentPropertySavingCallback;
22+
import io.github.kaiso.relmongo.model.LoadableObjectsMetadata;
23+
import io.github.kaiso.relmongo.mongo.PersistentRelationResolver;
2024

2125
import org.springframework.beans.factory.annotation.Autowired;
2226
import org.springframework.data.mongodb.core.MongoOperations;
@@ -26,8 +30,7 @@
2630
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
2731
import org.springframework.util.ReflectionUtils;
2832

29-
import java.util.Map;
30-
import java.util.Map.Entry;
33+
import java.util.List;
3134

3235
public class MongoEventListener extends AbstractMongoEventListener<Object> {
3336

@@ -38,7 +41,7 @@ public class MongoEventListener extends AbstractMongoEventListener<Object> {
3841
public void onAfterLoad(AfterLoadEvent<Object> event) {
3942
PersistentPropertyLoadingCallback callback = new PersistentPropertyLoadingCallback(event.getSource());
4043
ReflectionUtils.doWithFields(event.getType(), callback);
41-
Map<Entry<Class<?>, FetchType>, Entry<Object, String>> loadableObjects = callback.getLoadableObjects();
44+
List<LoadableObjectsMetadata> loadableObjects = callback.getLoadableObjects();
4245
if(!loadableObjects.isEmpty()) {
4346
PersistentRelationResolver.resolveOnLoading(mongoOperations, loadableObjects, event.getSource());
4447
}

0 commit comments

Comments
 (0)