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 package org.melati.poem;
45
46 import java.lang.reflect.Method;
47 import java.util.Enumeration;
48
49 import org.melati.poem.util.ClassUtils;
50 import org.melati.poem.util.StringUtils;
51
52
53
54
55
56
57
58
59 public final class PersistentFactory {
60
61
62
63
64 private PersistentFactory() {
65 }
66
67
68
69
70
71
72
73
74 public static Persistent fromInstance(Database db, Object pojo) {
75 System.err.println("fromInstance - looking for " + pojo.getClass().getName());
76 Table<?> table = null;
77 Persistent p = null;
78 if (pojo instanceof Persistent) {
79 if (((Persistent)pojo).troid() != null) {
80 return (Persistent)pojo;
81 } else {
82 p = populatedPersistent(((Persistent)pojo).getTable(), pojo);
83 p.makePersistent();
84 return p;
85 }
86 } else
87 table = TableFactory.fromInstance(db, pojo);
88 p = populatedPersistent(table, pojo);
89 Enumeration<?> candidates = table.selection(p);
90 while (candidates.hasMoreElements()) {
91 Persistent candidate = (Persistent)candidates.nextElement();
92 if (commonFieldsEqual(p, candidate)) {
93 p = candidate;
94 System.err.println("Candidate: " + p);
95 break;
96 } else
97 System.err.println("Non Candidate: " + p);
98 }
99 if (p.getTroid() == null) {
100 System.err.println("About to persist : " + p);
101 p.makePersistent();
102 System.err.println("Have persisted : " + p);
103 }
104 System.err.println("Returning : " + p);
105 return p;
106 }
107
108 private static boolean commonFieldsEqual(Persistent criterion, Persistent candidate) {
109 Enumeration<Column<?>> cols = criterion.getTable().columns();
110 while (cols.hasMoreElements()) {
111 Column<?> col = (Column<?>)cols.nextElement();
112 if (col.isTroidColumn())
113 continue;
114 if (col.getRaw(criterion) != null &&
115 !col.getRaw(criterion).equals(col.getRaw(candidate))) {
116 System.err.println("Reject");
117 return false;
118 }
119 }
120 return true;
121 }
122
123
124
125
126
127
128
129
130 public static Persistent populatedPersistent(Table<?> table, Object pojo) {
131 if (pojo instanceof Persistent)
132 if (((Persistent)pojo).troid() != null)
133 return table.getObject(((Persistent)pojo).troid().intValue());
134 else
135 return ((Persistent)pojo);
136 Persistent p = table.newPersistent();
137 Class<?> c = pojo.getClass();
138 Enumeration<Column<?>> columns = table.columns();
139 while (columns.hasMoreElements()) {
140 Column<?> col = (Column<?>)columns.nextElement();
141 if(col.isTroidColumn()) continue;
142 Method memberGetter;
143 Object raw;
144 try {
145 memberGetter = c.getMethod("get" + StringUtils.capitalised(col.getName()),
146 new Class[] {});
147 } catch (NoSuchMethodException e) {
148 try {
149 memberGetter = c.getMethod("is" + StringUtils.capitalised(col.getName()),
150 new Class[] {});
151 } catch (NoSuchMethodException e1) {
152 throw new AppBugPoemException(
153 "No getter available for field " + col.getName() +
154 " on object of class " + pojo.getClass().getName(), e1);
155 }
156 }
157 try {
158 raw = memberGetter.invoke(pojo, new Object[] {});
159 } catch (Exception e) {
160 throw new AppBugPoemException(
161 "Problem invoking getter on column " + col.getName(), e);
162 }
163 if (raw != null) {
164 try {
165 if (col.getType() instanceof PersistentReferencePoemType) {
166 p.setCooked(col.getName(),
167 PersistentFactory.fromInstance(table.getDatabase(), raw));
168 } else {
169 p.setCooked(col.getName(), raw);
170 }
171 } catch (TypeMismatchPoemException e) {
172 throw new AppBugPoemException("Problem setting value of Column "
173 + col.getName(), e);
174 }
175 }
176 }
177 return p;
178 }
179
180
181
182
183
184
185
186
187
188
189
190 public static Object from(Persistent persistent, Class<?> clazz)
191 throws NoSuchMethodException {
192 Object it;
193 try {
194 it = clazz.newInstance();
195 } catch (Exception e) {
196 throw new AppBugPoemException("Problem creating new instance of "
197 + clazz.getName(), e);
198 }
199 return populatedPojo(it, persistent);
200 }
201
202 private static Object populatedPojo(Object pojo, Persistent persistent)
203 throws NoSuchMethodException {
204 Enumeration<Column<?>> columns = persistent.getTable().columns();
205 while (columns.hasMoreElements()) {
206 Column<?> col = (Column<?>)columns.nextElement();
207 if(col.isTroidColumn() && !(pojo instanceof Persistent)) continue;
208 Object cooked = col.getCooked(persistent);
209 if (cooked != null) {
210 String setterName = "set" + StringUtils.capitalised(col.getName());
211 Method[] possibleSetters = ClassUtils.getOneArgumentMethods(pojo.getClass(), setterName);
212 if(possibleSetters.length == 0)
213 throw new NoSuchMethodException("No setter called " + setterName
214 + " could be found " + "on Class " + pojo.getClass().getName());
215 for (int i = 0; i < possibleSetters.length; i++) {
216 if (col.getType() instanceof ReferencePoemType) {
217 Object newPojo = PersistentFactory.from((Persistent)cooked,
218 possibleSetters[i].getParameterTypes()[0]);
219 try {
220 possibleSetters[i].invoke(pojo, new Object[] { newPojo });
221 } catch (Exception e) {
222 throw new AppBugPoemException(
223 "Problem setting value of Column " + col.getName(), e);
224 }
225 } else {
226 try {
227 possibleSetters[i].invoke(pojo, new Object[] { cooked });
228 } catch (Exception e) {
229 throw new AppBugPoemException(
230 "Problem setting value of Column " + col.getName(), e);
231 }
232 }
233 }
234 }
235 }
236 return pojo;
237 }
238
239
240 }