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.util.Collections;
24 import java.util.HashMap;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.SortedMap;
29
30 import pl.edu.agh.cast.model.mapper.AttributeLoader;
31 import pl.edu.agh.cast.model.mapper.Direction;
32 import pl.edu.agh.cast.model.mapper.Link;
33 import pl.edu.agh.cast.model.mapper.LinkLoader;
34 import pl.edu.agh.cast.model.mapper.Mappable;
35 import pl.edu.agh.cast.model.mapper.Mapper;
36 import pl.edu.agh.cast.model.mapper.Node;
37 import pl.edu.agh.cast.model.mapper.annotation.MapAttribute;
38 import pl.edu.agh.cast.model.mapper.annotation.MapLink;
39 import pl.edu.agh.cast.model.mapper.annotation.Mapping;
40
41
42
43
44
45
46
47 public class DBLoader extends AbstractLoader {
48
49
50
51
52 private static final String SET_PREFIX = "set";
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public DBLoader(Map<Node, Mappable> objectCache, Class<Mappable> klass, Map<String, Class> typeMap2,
67 SortedMap<String, Object> conditions) {
68 super(objectCache, klass, typeMap2, conditions);
69 }
70
71
72
73
74
75
76
77 public List<Mappable> find() {
78 if (!Mapper.isDBPresent()) {
79 log.warn("DB is not initialized");
80 return new LinkedList<Mappable>();
81 }
82
83 Mapping mapping = klass.getAnnotation(Mapping.class);
84 if (mapping == null) {
85 throw new IllegalArgumentException("Class " + klass
86 + " is not mapped to metamodel");
87 }
88 if (typeMap == null) {
89 typeMap = new HashMap<String, Class>();
90 }
91 String typeName = Helper.mappedTypeName(klass);
92 if (typeMap.get(typeName) == null) {
93 typeMap.put(typeName, klass);
94 }
95 try {
96 List<Node> nodes = null;
97 if (conditions == null) {
98 nodes = Node.find(typeName);
99 } else {
100 nodes = Node.find(typeName, conditions);
101 }
102 List<Mappable> result = new LinkedList<Mappable>();
103
104 for (Node node : nodes) {
105 result.add(load(node));
106 }
107 return result;
108 } catch (Exception ex) {
109 ex.printStackTrace();
110 }
111 return Collections.emptyList();
112 }
113
114
115
116
117
118
119
120
121
122 private Mappable load(Node node) throws Exception {
123 Mappable cached = objectCache.get(node);
124 Class<Mappable> klass = Helper.mappedClass(node.getTypeName(), typeMap);
125
126 if (cached != null && cached.getClass().equals(klass)) {
127 return cached;
128 }
129
130 Constructor<Mappable> constructor = Helper.getConstructor(klass);
131 Mappable newInstance = constructor.newInstance((Object[])null);
132 newInstance.setMid(node.getId());
133 objectCache.put(node, newInstance);
134 loadAttributes(node, newInstance, klass);
135 loadLinks(node, newInstance, klass);
136 return newInstance;
137 }
138
139
140
141
142
143
144
145
146
147
148
149
150 private void loadLinks(Node node, Mappable object, Class<Mappable> klass) throws Exception {
151 if (Helper.isSuperMapped(klass)) {
152 loadLinks(node, object, (Class<Mappable>)klass.getSuperclass());
153 }
154
155
156
157 for (LinkEntry entry : Helper.getMappedLinks(klass)) {
158
159 MapLink linkMapping = entry.getAnnotation();
160 Direction direction = linkMapping.direction();
161
162
163 List<Link> links = node.links(linkMapping.name(), direction);
164 String setterName = null;
165
166
167 List<Mappable> linkedElements = new LinkedList<Mappable>();
168 for (Link link : links) {
169 if (direction == Direction.SRC) {
170
171
172 if (setterName == null) {
173 setterName = SET_PREFIX + link.getSrcAccessor();
174 }
175
176 linkedElements.add(load(link.getDst()));
177 } else {
178 if (setterName == null) {
179 setterName = SET_PREFIX + link.getDstAccessor();
180 }
181 linkedElements.add(load(link.getSrc()));
182 }
183 }
184 if (linkMapping.load().equals(Object.class)) {
185
186 if (linkedElements.size() == 0) {
187
188
189
190
191
192
193
194
195
196 } else {
197 if (setterName == null) {
198 throw new RuntimeException("Metamodel error: missing link setter for "
199 + "link " + linkMapping.name()
200 + " for " + klass + " ["
201 + node.getId() + "]");
202 }
203 Type klass2 = entry.getMethod().getReturnType();
204 if (klass2 != null && klass2.equals(List.class)) {
205 Method setter = object.getClass().getMethod(setterName, List.class);
206 setter.invoke(object, new Object[] { linkedElements });
207 } else {
208 if (linkedElements.size() > 1) {
209 throw new RuntimeException("Too many values for singular link "
210 + linkMapping.name() + " for "
211 + klass + " [" + node.getId()
212 + "]");
213 }
214 Object linkedElement = linkedElements.get(0);
215 Method setter = Helper.getSetter(object, linkedElement, setterName);
216 setter.invoke(object, new Object[] { linkedElement });
217 }
218 }
219 } else {
220 Constructor cons = linkMapping.load().getConstructor(new Class[] { klass });
221 LinkLoader loader = (LinkLoader)cons.newInstance(new Object[] { object });
222 loader.loadLink(linkedElements);
223 }
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 private void loadAttributes(Node node, Mappable object, Class<Mappable> klass) throws Exception {
242 if (Helper.isSuperMapped(klass)) {
243 loadAttributes(node, object, (Class<Mappable>)klass.getSuperclass());
244 }
245
246 for (Method method : Helper.mappedAttributeMethods(klass)) {
247 MapAttribute attributeMapping = method.getAnnotation(MapAttribute.class);
248 String attributeName = attributeMapping.name();
249 if (attributeName.equals("")) {
250 attributeName = method.getName();
251 }
252 try {
253 List<Link> links = node.links(attributeName);
254 if (attributeMapping.load().equals(Object.class)) {
255
256
257 if (links.size() > 1) {
258 throw new RuntimeException("Too many values for attribute "
259 + attributeName + " for " + klass + "["
260 + node.getId() + "]");
261 } else if (links.size() != 1) {
262
263
264
265 throw new RuntimeException("Missing value for attribute " + attributeName
266 + " for " + klass + "[" + node.getId()
267 + "]");
268 } else {
269 String setterName = SET_PREFIX + method.getName().substring(3);
270 Method setterMethod = klass.getMethod(setterName, method.getReturnType());
271 Object value = links.get(0).getSrc().getValue();
272 try {
273 setterMethod.invoke(object, new Object[] { value });
274 } catch (IllegalArgumentException ex) {
275 if (value instanceof Long) {
276 Integer intValue = ((Long)value).intValue();
277 setterMethod.invoke(object, new Object[] { intValue });
278 }
279 }
280 }
281 } else {
282 Constructor cons = attributeMapping.load().getConstructor(new Class[] { klass });
283 AttributeLoader loader = (AttributeLoader)cons.newInstance(new Object[] { object });
284 loader.loadAttribute(node, links);
285 }
286 } catch (NoSuchMethodException e) {
287 throw new RuntimeException("Missing setter for attribute "
288 + attributeName + " for " + klass, e);
289 }
290 }
291 }
292
293 }