1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package p3j.database.hibernate;
17
18 import james.SimSystem;
19 import james.core.data.DBConnectionData;
20 import james.core.util.StopWatch;
21
22 import java.sql.Connection;
23 import java.sql.DriverManager;
24 import java.sql.SQLException;
25 import java.util.List;
26 import java.util.logging.Level;
27
28 import org.hibernate.SessionFactory;
29 import org.hibernate.Transaction;
30 import org.hibernate.cfg.Configuration;
31 import org.hibernate.classic.Session;
32 import org.hibernate.criterion.Order;
33 import org.hibernate.criterion.Restrictions;
34 import org.hibernate.tool.hbm2ddl.SchemaExport;
35
36 import p3j.database.IP3MDatabase;
37 import p3j.database.IProjectionResultsIterator;
38 import p3j.experiment.results.ResultsOfTrial;
39 import p3j.gui.misc.P3JConfigFile;
40 import p3j.misc.IProgressObserver;
41 import p3j.misc.MatrixDimension;
42 import p3j.misc.Misc;
43 import p3j.misc.math.Matrix;
44 import p3j.misc.math.Matrix2D;
45 import p3j.pppm.ProjectionModel;
46 import p3j.pppm.parameters.Parameter;
47 import p3j.pppm.parameters.ParameterAssignment;
48 import p3j.pppm.parameters.ParameterInstance;
49 import p3j.pppm.parameters.Parameters;
50 import p3j.pppm.parameters.Population;
51 import p3j.pppm.sets.Set;
52 import p3j.pppm.sets.SetType;
53
54
55
56
57
58
59
60
61
62
63 public class P3MDatabase implements IP3MDatabase {
64
65
66 private static String hibernateConfigFile = Misc.DEFAULT_HIBERNATE_CONFIG_FILE;
67
68
69 private static final int DEFAULT_FLUSH_FREQ = 50;
70
71
72 private boolean alwaysFlush = true;
73
74
75 private final Configuration config;
76
77
78 private SessionFactory sessionFactory;
79
80
81 private Session session;
82
83
84 private Session resultStorageSession;
85
86
87 private int resultStorageCounter;
88
89
90
91
92
93 private int resultStorageFlushFrequency = DEFAULT_FLUSH_FREQ;
94
95
96
97
98 public P3MDatabase() {
99 this(P3MDatabase.hibernateConfigFile);
100 }
101
102
103
104
105
106
107
108 public P3MDatabase(String configurationFile) {
109 config = new Configuration().configure(configurationFile);
110 }
111
112 @Override
113 public void init(DBConnectionData dbConn, P3JConfigFile configFile) {
114 getConfig()
115 .setProperty("hibernate.connection.username", dbConn.getUser())
116 .setProperty("hibernate.connection.url", dbConn.getUrl())
117 .setProperty(Misc.PREF_HIBERNATE_DRIVER_PROPERTY, dbConn.getDriver())
118 .setProperty(Misc.PREF_HIBERNATE_DIALECT_PROPERTY,
119 Misc.HIBERNATE_DIALECTS.get(configFile.get(Misc.PREF_DB_TYPE)));
120
121 if (!dbConn.getPassword().isEmpty())
122 getConfig().setProperty("hibernate.connection.password",
123 dbConn.getPassword());
124
125 sessionFactory = getConfig().buildSessionFactory();
126 }
127
128 @Override
129 public void open() {
130 if (session == null) {
131 session = sessionFactory.openSession();
132 }
133 }
134
135 @Override
136 public void clear() {
137 SimSystem.report(Level.INFO, "CLEARING DB...");
138 SchemaExport export = new SchemaExport(getConfig());
139 export.create(true, true);
140 }
141
142 @Override
143 public void close() {
144 if (session != null) {
145 session.close();
146 }
147 if (sessionFactory != null) {
148 sessionFactory.close();
149 }
150 }
151
152
153
154
155 protected void dbChanged() {
156 if (alwaysFlush) {
157 session.flush();
158 }
159 }
160
161
162
163
164
165
166
167 public void save(Object o) {
168 Transaction t = session.beginTransaction();
169 session.save(o);
170 t.commit();
171 dbChanged();
172 }
173
174
175
176
177
178
179
180 public void delete(Object o) {
181 Transaction t = session.beginTransaction();
182 session.delete(o);
183 t.commit();
184 dbChanged();
185 }
186
187
188
189 @Override
190 public Parameter newParameter(String name, boolean genDep,
191 MatrixDimension height, MatrixDimension width, Population population) {
192 Parameter param = getParameter(name);
193 if (param == null) {
194 param = new Parameter(-1, genDep, name, height, width, population);
195 save(param);
196 }
197 return param;
198 }
199
200 @Override
201 public Parameter getParameter(String name) {
202 List<Parameter> parameters = Misc.autoCast(session.createQuery(
203 "from Parameter where name='" + name + "'").list());
204 if (parameters.size() > 1) {
205 throw new ConstraintException(
206 "Ambiguity: there are two parameters with the same name '" + name
207 + "'");
208 }
209 if (parameters.size() == 1) {
210 return parameters.get(0);
211 }
212 return null;
213 }
214
215 @Override
216 public List<Parameter> getAllParameters() {
217 List<Parameter> parameters = Misc.autoCast(session.createQuery(
218 "from Parameter").list());
219 return parameters;
220 }
221
222 @Override
223 public boolean deleteParameter(Parameter parameter) {
224 delete(parameter);
225 return true;
226 }
227
228
229
230 @Override
231 public ParameterInstance newParameterInstance(int comparisonIndex,
232 Parameter param, int generation) {
233 ParameterInstance instance = getParameterInstance(param, generation);
234 if (instance == null) {
235 instance = new ParameterInstance(comparisonIndex, param, generation);
236 save(instance);
237 }
238 return instance;
239 }
240
241 @Override
242 public ParameterInstance getParameterInstance(Parameter param, int generation) {
243 List<ParameterInstance> instances = Misc.autoCast(session
244 .createCriteria(ParameterInstance.class)
245 .add(Restrictions.eq("parameter", param))
246 .add(Restrictions.eq("generation", generation)).list());
247 if (instances.size() > 1) {
248 throw new ConstraintException(
249 "Ambiguity: there are two parameter instances for parameter '"
250 + param.getName() + "' and generation " + generation);
251 }
252 if (instances.size() == 1) {
253 return instances.get(0);
254 }
255 return null;
256 }
257
258 @Override
259 public List<ParameterInstance> getAllParameterInstances() {
260 List<ParameterInstance> instances = Misc.autoCast(session.createQuery(
261 "from ParameterInstance").list());
262 return instances;
263 }
264
265 @Override
266 public boolean deleteParameterInstance(ParameterInstance instance) {
267 delete(instance);
268 return true;
269 }
270
271
272
273 @Override
274 public Matrix newMatrix(Matrix2D value) {
275 Matrix matrix = getMatrix(value);
276 if (matrix == null) {
277 matrix = new Matrix(value);
278 save(matrix);
279 }
280 return matrix;
281 }
282
283 @Override
284 public Matrix getMatrix(Matrix2D value) {
285 List<Matrix> matrices = Misc
286 .autoCast(session.createCriteria(Matrix.class)
287 .add(Restrictions.eq("hash", Matrix2D.calculateHashCode(value)))
288 .list());
289 for (Matrix matrix : matrices) {
290 if (matrix.getValue().equals(value)) {
291 return matrix;
292 }
293 }
294 return null;
295 }
296
297 @Override
298 public List<Matrix> getAllMatrices() {
299 List<Matrix> matrices = Misc.autoCast(session.createQuery("from Matrix")
300 .list());
301 return matrices;
302 }
303
304 @Override
305 public boolean deleteMatrix(Matrix matrix) {
306 delete(matrix);
307 return true;
308 }
309
310
311
312 @Override
313 public ParameterAssignment newParameterAssignment(
314 ParameterInstance paramInstance, String name, String description,
315 double probability, double deviation, Matrix2D value) {
316 Matrix matrix = newMatrix(value);
317 ParameterAssignment assignment = new ParameterAssignment(paramInstance,
318 name, description, probability, deviation, matrix);
319 save(assignment);
320 return assignment;
321 }
322
323 @Override
324 public List<ParameterAssignment> getAllParameterAssignments(
325 ParameterInstance param) {
326 List<ParameterAssignment> assignments = Misc.autoCast(session
327 .createCriteria(ParameterAssignment.class)
328 .add(Restrictions.eq("paramInstance", param)).list());
329 return assignments;
330 }
331
332 @Override
333 public boolean deleteParameterAssignment(ParameterAssignment assignment) {
334 delete(assignment);
335 return true;
336 }
337
338 @Override
339 public void saveParameterAssignment(ParameterAssignment assignment) {
340 save(assignment);
341 }
342
343
344
345 @Override
346 public Set newSet(List<ParameterInstance> defParams, String name,
347 String desc, double prob) {
348 Set set = new Set(defParams, name, desc, prob);
349 save(set);
350 return set;
351 }
352
353 @Override
354 public void saveSet(Set set) {
355 save(set);
356 }
357
358 @Override
359 public List<Set> getAllSets() {
360 return Misc.autoCast(session.createCriteria(Set.class).list());
361 }
362
363 @Override
364 public boolean deleteSet(Set set) {
365 delete(set);
366 return true;
367 }
368
369
370
371 @Override
372 public SetType newSetType(String name, String description) {
373 SetType setType = new SetType(name, description);
374 save(setType);
375 return setType;
376 }
377
378 @Override
379 public List<SetType> getAllSetTypes() {
380 List<SetType> setTypes = Misc.autoCast(session
381 .createCriteria(SetType.class).list());
382 return setTypes;
383 }
384
385 @Override
386 public void saveSetType(SetType setType) {
387 save(setType);
388 }
389
390 @Override
391 public boolean deleteSeType(SetType setType) {
392 delete(setType);
393 return true;
394 }
395
396
397
398 @Override
399 public void newProjection(ProjectionModel projection) {
400
401 List<Parameter> parameters = Parameters.getInstance().getParams();
402 List<ParameterInstance> allInstances = projection
403 .getAllParameterInstances();
404 int comparisonIndex = 0;
405 for (int j = 0; j < projection.getGenerations(); j++) {
406 for (int i = 0; i < parameters.size(); i++) {
407 Parameter parameter = parameters.get(i);
408 if (parameter.isGenerationDependent()) {
409 allInstances
410 .add(newParameterInstance(++comparisonIndex, parameter, j));
411 } else if (j == 0) {
412 allInstances.add(newParameterInstance(++comparisonIndex, parameter,
413 -1));
414 }
415 }
416 }
417 projection.init();
418 save(projection);
419 }
420
421 @Override
422 public boolean deleteProjection(ProjectionModel projection,
423 IProgressObserver observer) {
424 deleteAllResults(projection, observer);
425 if (observer != null) {
426 observer.addWaypoints(1);
427 observer.incrementProgress("Deleting projection...");
428 }
429 delete(projection);
430 return true;
431 }
432
433 @Override
434 public List<ProjectionModel> getAllProjections() {
435 List<ProjectionModel> projections = Misc.autoCast(session.createQuery(
436 "from ProjectionModel").list());
437 return projections;
438 }
439
440 @Override
441 public ProjectionModel getProjectionByID(int id) {
442 List<ProjectionModel> pModels = Misc.autoCast(session
443 .createCriteria(ProjectionModel.class).add(Restrictions.eq("ID", id))
444 .list());
445 if (pModels.size() > 1) {
446 throw new ConstraintException(
447 "DB consistency: Two duplicate projection models with the same ID '"
448 + id + "' !");
449 }
450 if (pModels.size() == 1) {
451 return pModels.get(0);
452 }
453 return null;
454 }
455
456 @Override
457 public void saveProjection(ProjectionModel projection) {
458 save(projection);
459 }
460
461
462
463
464
465
466
467
468
469 public static Exception testConnection(DBConnectionData dbConnData) {
470 Connection c = null;
471 try {
472 c = DriverManager.getConnection(dbConnData.getUrl(),
473 dbConnData.getUser(), dbConnData.getPassword());
474 if (c == null) {
475 throw new IllegalArgumentException(
476 "Connection created by driver manager is null.");
477 }
478 } catch (Exception ex) {
479 return ex;
480 } finally {
481 try {
482 if (c != null) {
483 c.close();
484 }
485 } catch (SQLException e) {
486 return e;
487 }
488 }
489 return null;
490 }
491
492
493
494
495
496
497
498
499
500
501
502
503
504 public static Exception testConnection(String dbURL, String dbUserName,
505 String dbPassword) {
506 return testConnection(new DBConnectionData(dbURL, dbUserName, dbPassword,
507 null));
508 }
509
510 @Override
511 public synchronized void saveTrialResults(ResultsOfTrial resultOfTrial) {
512 if (resultStorageSession == null) {
513 resultStorageSession = sessionFactory.openSession();
514 }
515 StopWatch sw = new StopWatch();
516 sw.start();
517 Transaction resultStorageTransaction = resultStorageSession
518 .beginTransaction();
519 resultStorageSession.save(resultOfTrial);
520 resultStorageTransaction.commit();
521 resultStorageCounter++;
522 if (resultStorageCounter % resultStorageFlushFrequency == 0) {
523 resultStorageSession.flush();
524 resultStorageSession.clear();
525 }
526 sw.stop();
527 SimSystem.report(Level.INFO,
528 "Time for result storage in database:" + sw.elapsedMilliseconds());
529 }
530
531 @Override
532 public List<ResultsOfTrial> getAllResults(ProjectionModel projection) {
533 List<ResultsOfTrial> results = Misc.autoCast(session
534 .createCriteria(ResultsOfTrial.class)
535 .add(Restrictions.eq("projection", projection))
536 .addOrder(Order.asc("ID")).list());
537 return results;
538 }
539
540 @Override
541 public void deleteResult(ResultsOfTrial resultOfTrial) {
542 delete(resultOfTrial);
543 }
544
545 @Override
546 public void deleteAllResults(ProjectionModel projection,
547 IProgressObserver observer) {
548 List<ResultsOfTrial> results = getAllResults(projection);
549
550 if (observer != null) {
551 observer.addWaypoints(results.size());
552 }
553
554 while (!results.isEmpty()) {
555 ResultsOfTrial result = results.remove(results.size() - 1);
556 Transaction t = session.beginTransaction();
557 session.delete(result);
558 t.commit();
559 session.evict(result);
560 if (observer != null) {
561 observer.incrementProgress("Deleted result with ID " + result.getID());
562 if (observer.isCancelled()) {
563 observer.taskCanceled();
564 break;
565 }
566 }
567 }
568 dbChanged();
569 }
570
571 @Override
572 public IProjectionResultsIterator getResultIterator(ProjectionModel projection) {
573 return new ProjectionResultsIterator(sessionFactory, projection.getID());
574 }
575
576 @Override
577 public void clearCache(Object o) {
578 session.evict(o);
579 session.flush();
580 }
581
582
583
584
585
586
587 public static String getHibernateConfigFile() {
588 return hibernateConfigFile;
589 }
590
591
592
593
594
595
596
597 public static void setHibernateConfigFile(String hibernateConfigFile) {
598 P3MDatabase.hibernateConfigFile = hibernateConfigFile;
599 }
600
601 public Configuration getConfig() {
602 return config;
603 }
604 }