1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package pl.edu.agh.cast.model.mapper.internal;
19
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.Method;
22 import java.lang.reflect.Type;
23 import java.sql.SQLException;
24 import java.util.List;
25
26 import pl.edu.agh.cast.model.mapper.AttributeSaver;
27 import pl.edu.agh.cast.model.mapper.Direction;
28 import pl.edu.agh.cast.model.mapper.Link;
29 import pl.edu.agh.cast.model.mapper.Mappable;
30 import pl.edu.agh.cast.model.mapper.Mapper;
31 import pl.edu.agh.cast.model.mapper.Node;
32 import pl.edu.agh.cast.model.mapper.Priority;
33 import pl.edu.agh.cast.model.mapper.annotation.MapLink;
34 import pl.edu.agh.cast.model.mapper.annotation.Mapping;
35
36
37
38
39
40
41
42 public class DBSaver extends AbstractSaver {
43
44
45
46
47
48
49
50
51
52 public DBSaver(Mappable object, boolean force) {
53 super(object, force);
54 }
55
56
57
58
59
60
61
62 public boolean save() {
63 if (!Mapper.isDBPresent()) {
64 log.warn("DB is not initialized");
65 return false;
66 }
67 try {
68 queue.addLast(primaryObject);
69 visited.add(primaryObject);
70 while (!queue.isEmpty()) {
71 Mappable element = queue.removeFirst();
72 Node node = internalSave(element);
73 Class klass = element.getClass();
74 saveLinks(element, node, klass);
75 stored.add(element);
76 }
77
78 return true;
79 } catch (Exception e) {
80 e.printStackTrace();
81 return false;
82 }
83 }
84
85 private Node internalSave(Mappable object) throws Exception {
86 Class<Mappable> klass = (Class<Mappable>)object.getClass();
87 if (klass.isAnnotationPresent(Mapping.class)) {
88 Node node;
89 long id = object.getMid();
90 if (id == 0) {
91 node = new Node(Helper.mappedTypeName(klass));
92 if (!node.save()) {
93 throw new RuntimeException("Node for object " + object
94 + " not saved.");
95 }
96 object.setMid(node.getId());
97 nodes.put(node.getId(), node);
98 } else {
99 node = nodes.get(id);
100 if (node == null) {
101 node = Node.find(id);
102 }
103 }
104 saveAttributes(object, node, object.getClass());
105 return node;
106 } else {
107 throw new IllegalArgumentException("Object " + object
108 + " not mapped.");
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122 private void saveLinks(Mappable object, Node node, Class<Mappable> klass) throws Exception {
123 if (Helper.isSuperMapped(klass)) {
124 saveLinks(object, node, (Class<Mappable>)klass.getSuperclass());
125
126
127
128 }
129
130
131 for (LinkEntry entry : Helper.getMappedLinks(klass)) {
132 Object linkedItem = entry.getMethod().invoke(object);
133 int position = 0;
134 if (linkedItem instanceof List) {
135 List<Mappable> items = (List<Mappable>)linkedItem;
136 for (Mappable item : items) {
137 createLink(entry.getAnnotation(), object, item, node, position);
138 position++;
139 }
140 } else {
141 createLink(entry.getAnnotation(), object, (Mappable)linkedItem, node, position);
142 }
143 }
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 private void createLink(MapLink linkMapping, Mappable thisItem, Mappable thatItem, Node thisNode, int dstPosition)
160 throws Exception {
161 if (!visited.contains(thatItem)) {
162 queue.addLast(thatItem);
163 visited.add(thatItem);
164 }
165
166 if (stored.contains(thatItem)) {
167
168 return;
169 }
170
171
172 Node thatNode = internalSave(thatItem);
173 String linkName = linkMapping.name();
174
175
176 Method method = Helper.getAnnotatedMethod(thatItem.getClass(), linkName);
177 int srcPosition = 0;
178 Type klass2 = method.getReturnType();
179 if (klass2 != null && klass2.equals(List.class)) {
180 Method setter = thatItem.getClass().getMethod(method.getName());
181 List elements = (List)setter.invoke(thatItem, new Object[] {});
182 for (Object element : elements) {
183 if (element.equals(thisItem)) {
184 break;
185 }
186 srcPosition++;
187 }
188 }
189
190
191 Link link;
192 if (linkMapping.direction() == Direction.DST) {
193
194
195 link = new Link(thatNode, thisNode, linkName, Priority.NONE, Helper.objectAccessor(thatItem.getClass(),
196 linkName), Helper.objectAccessor(thisItem.getClass(), linkName), dstPosition, srcPosition);
197 } else {
198
199
200 link = new Link(thisNode, thatNode, linkName, Priority.NONE, Helper.objectAccessor(thisItem.getClass(),
201 linkName), Helper.objectAccessor(thatItem.getClass(), linkName), srcPosition, dstPosition);
202 }
203
204
205
206 link.save();
207 }
208
209
210
211
212
213
214
215
216
217
218 private void saveAttributes(Mappable object, Node node, Class klass) throws Exception {
219 if (Helper.isSuperMapped(klass)) {
220 saveAttributes(object, node, klass.getSuperclass());
221 }
222
223
224
225 for (AttributeEntry entry : Helper.getMappedAttributes(klass)) {
226 Object value = entry.getMethod().invoke(object);
227 String attributeName = entry.getAnnotation().name();
228 if (attributeName.equals("")) {
229 attributeName = entry.getMethod().getName();
230 }
231 List<Link> links = node.links(attributeName);
232 if (entry.getAnnotation().save().equals(Object.class)) {
233
234 Node attributeNode;
235 if (links.size() == 0) {
236
237 attributeNode = new Node(entry.getAnnotation().typeName(), value);
238 Link link = node.addDependent(attributeNode, attributeName);
239 attributeNode.save();
240 link.save();
241 } else {
242
243 if (links.size() != 1) {
244 throw new RuntimeException("Too many links for attribute " + attributeName
245 + " for " + klass + "[" + node.getId()
246 + "]");
247 } else {
248 attributeNode = links.get(0).getSrc();
249 attributeNode.setValue(value);
250 attributeNode.save();
251 }
252 }
253 } else {
254 Constructor cons = entry.getAnnotation().save().getConstructor(new Class[] { klass });
255 AttributeSaver saver = (AttributeSaver)cons.newInstance(new Object[] { object });
256 saver.saveAttribute(node, links);
257 }
258 }
259 }
260 }