-
Notifications
You must be signed in to change notification settings - Fork 2
/
ObjectGraphTraverser.java
114 lines (95 loc) · 3.53 KB
/
ObjectGraphTraverser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package cz.cvut.kbss.jsonld.serialization.traversal;
import cz.cvut.kbss.jsonld.common.BeanAnnotationProcessor;
import cz.cvut.kbss.jsonld.common.BeanClassProcessor;
import cz.cvut.kbss.jsonld.exception.JsonLdSerializationException;
import java.lang.reflect.Field;
import java.util.*;
public class ObjectGraphTraverser implements InstanceVisitor {
private static final Object EMPTY_OBJECT = new Object();
private final Set<InstanceVisitor> visitors = new HashSet<>(4);
private Map<Object, Object> knownInstances;
public void addVisitor(InstanceVisitor visitor) {
Objects.requireNonNull(visitor);
visitors.add(visitor);
}
public void removeVisitor(InstanceVisitor visitor) {
visitors.remove(visitor);
}
private void resetKnownInstances() {
this.knownInstances = new IdentityHashMap<>();
}
public void traverse(Object instance) {
Objects.requireNonNull(instance);
resetKnownInstances();
try {
if (instance instanceof Collection) {
traverseCollection((Collection<?>) instance);
} else {
traverseImpl(instance);
}
} catch (IllegalAccessException e) {
throw new JsonLdSerializationException("Unable to extract field value.", e);
}
}
private void traverseCollection(Collection<?> col) throws IllegalAccessException {
openCollection(col);
for (Object item : col) {
traverseImpl(item);
}
closeCollection(col);
}
private void traverseImpl(Object instance) throws IllegalAccessException {
if (knownInstances.containsKey(instance)) {
visitKnownInstance(instance);
return;
}
openInstance(instance);
for (Field f : BeanAnnotationProcessor.getSerializableFields(instance)) {
final Object value = BeanClassProcessor.getFieldValue(f, instance);
visitField(f, value);
if (value != null && BeanAnnotationProcessor.isObjectProperty(f)) {
traverseObjectPropertyValue(value);
}
}
closeInstance(instance);
}
private void traverseObjectPropertyValue(Object value) throws IllegalAccessException {
if (value instanceof Collection) {
final Collection<?> col = (Collection<?>) value;
openCollection(col);
for (Object elem : col) {
traverseImpl(elem);
}
closeCollection(col);
} else if (value.getClass().isArray()) {
throw new JsonLdSerializationException("Arrays are not supported, yet.");
} else {
traverseImpl(value);
}
}
@Override
public void openInstance(Object instance) {
knownInstances.put(instance, EMPTY_OBJECT);
visitors.forEach(v -> v.openInstance(instance));
}
@Override
public void closeInstance(Object instance) {
visitors.forEach(v -> v.closeInstance(instance));
}
@Override
public void visitKnownInstance(Object instance) {
visitors.forEach(v -> v.visitKnownInstance((instance)));
}
@Override
public void visitField(Field field, Object value) {
visitors.forEach(v -> v.visitField(field, value));
}
@Override
public void openCollection(Collection<?> collection) {
visitors.forEach(v -> v.openCollection(collection));
}
@Override
public void closeCollection(Collection<?> collection) {
visitors.forEach(v -> v.closeCollection(collection));
}
}