1 package org.apache.ojb.broker.util.sequence;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.sql.ResultSet;
19 import java.sql.Statement;
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.Properties;
23 import java.util.Vector;
24
25 import org.apache.ojb.broker.PersistenceBroker;
26 import org.apache.ojb.broker.PersistenceBrokerException;
27 import org.apache.ojb.broker.accesslayer.StatementManagerIF;
28 import org.apache.ojb.broker.metadata.ClassDescriptor;
29 import org.apache.ojb.broker.metadata.FieldDescriptor;
30 import org.apache.ojb.broker.query.Query;
31 import org.apache.ojb.broker.util.logging.Logger;
32 import org.apache.ojb.broker.util.logging.LoggerFactory;
33
34
35
36
37
38
39
40 public class SequenceManagerHelper
41 {
42 private static Logger log = LoggerFactory.getLogger(SequenceManagerHelper.class);
43
44
45
46
47 public static final String PROP_SEQ_AS = "seq.as";
48
49
50
51
52 public static final String PROP_SEQ_START_OLD = "sequenceStart";
53
54
55
56 public static final String PROP_SEQ_START = "seq.start";
57
58
59
60 public static final String PROP_SEQ_INCREMENT_BY = "seq.incrementBy";
61
62
63
64 public static final String PROP_SEQ_MAX_VALUE = "seq.maxValue";
65
66
67
68 public static final String PROP_SEQ_MIN_VALUE = "seq.minValue";
69
70
71
72 public static final String PROP_SEQ_CYCLE = "seq.cycle";
73
74
75
76 public static final String PROP_SEQ_CACHE = "seq.cache";
77
78
79
80 public static final String PROP_SEQ_ORDER = "seq.order";
81
82 private static final String SEQ_PREFIX = "SEQ_";
83 private static final String SEQ_UNASSIGNED = "UNASSIGNED";
84 private static final String SM_SELECT_MAX = "SELECT MAX(";
85 private static final String SM_FROM = ") FROM ";
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 public static String buildSequenceName(PersistenceBroker brokerForClass,
114 FieldDescriptor field, boolean autoNaming)
115 throws SequenceManagerException
116 {
117 String seqName = field.getSequenceName();
118
119
120
121
122 if (seqName != null && seqName.trim().length() != 0)
123 {
124 return seqName;
125 }
126 else if (!autoNaming)
127 {
128
129
130
131
132
133 throw new SequenceManagerException("Could not find sequence-name for field '" +
134 field + "' of class '" + field.getClassDescriptor().getClassNameOfObject() +
135 "', property 'autoNaming' in sequence-manager element in repository was '" +
136 autoNaming + "'. Set autoNaming true in sequence-descriptor or define a " +
137 " sequence-name in field-descriptor.");
138 }
139
140 ClassDescriptor cldTargetClass = field.getClassDescriptor();
141
142
143
144 cldTargetClass = findInheritanceRoot(cldTargetClass);
145 Class topLevel = brokerForClass.getTopLevelClass(cldTargetClass.getClassOfObject());
146 ClassDescriptor cldTopLevel = brokerForClass.getClassDescriptor(topLevel);
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 if (cldTopLevel.isExtent())
162 {
163
164
165
166
167
168
169
170
171
172
173
174 seqName = firstFoundTableName(brokerForClass, cldTopLevel);
175 }
176 else
177 {
178 seqName = cldTargetClass.getFullTableName();
179 }
180
181 if (seqName == null)
182 {
183 seqName = SEQ_UNASSIGNED;
184 log.warn("Too complex structure, can not assign automatic sequence name for field '" +
185 field.getAttributeName() + "' in class '" +
186 field.getClassDescriptor().getClassNameOfObject() +
187 "'. Use a default sequence name instead: " + (SEQ_PREFIX + seqName));
188 }
189
190 seqName = SEQ_PREFIX + seqName;
191 if (log.isDebugEnabled())
192 log.debug("Set automatic generated sequence-name for field '" +
193 field.getAttributeName() + "' in class '" +
194 field.getClassDescriptor().getClassNameOfObject() +
195 "'.");
196 field.setSequenceName(seqName);
197 return seqName;
198 }
199
200
201
202
203
204
205 private static ClassDescriptor findInheritanceRoot(ClassDescriptor cld)
206 {
207 ClassDescriptor result = cld;
208 if(cld.getSuperClassDescriptor() != null)
209 {
210 result = findInheritanceRoot(cld.getSuperClassDescriptor());
211 }
212 return result;
213 }
214
215
216
217
218
219
220 private static String firstFoundTableName(PersistenceBroker brokerForClass, ClassDescriptor cld)
221 {
222 String name = null;
223 if (!cld.isInterface() && cld.getFullTableName() != null)
224 {
225 return cld.getFullTableName();
226 }
227 if (cld.isExtent())
228 {
229 Collection extentClasses = cld.getExtentClasses();
230 for (Iterator iterator = extentClasses.iterator(); iterator.hasNext();)
231 {
232 name = firstFoundTableName(brokerForClass, brokerForClass.getClassDescriptor((Class) iterator.next()));
233
234 if (name != null) break;
235 }
236 }
237 return name;
238 }
239
240
241
242
243
244
245
246
247
248 public static long getMaxForExtent(PersistenceBroker brokerForClass, FieldDescriptor field) throws PersistenceBrokerException
249 {
250 if (field == null)
251 {
252 log.error("Given FieldDescriptor was null, could not detect max value across all extents");
253 return 0;
254
255 }
256
257 Class topLevel = brokerForClass.getTopLevelClass(field.getClassDescriptor().getClassOfObject());
258 return getMaxId(brokerForClass, topLevel, field);
259 }
260
261
262
263
264
265 public static long getMaxId(PersistenceBroker brokerForClass, Class topLevel, FieldDescriptor original) throws PersistenceBrokerException
266 {
267 long max = 0;
268 long tmp;
269 ClassDescriptor cld = brokerForClass.getClassDescriptor(topLevel);
270
271
272 if (!cld.isInterface() && !cld.isAbstract())
273 {
274 tmp = getMaxIdForClass(brokerForClass, cld, original);
275 if (tmp > max)
276 {
277 max = tmp;
278 }
279 }
280
281 if (cld.isExtent())
282 {
283 Vector extentClasses = cld.getExtentClasses();
284 for (int i = 0; i < extentClasses.size(); i++)
285 {
286 Class extentClass = (Class) extentClasses.get(i);
287 if (cld.getClassOfObject().equals(extentClass))
288 {
289 throw new PersistenceBrokerException("Circular extent in " + extentClass +
290 ", please check the repository");
291 }
292 else
293 {
294
295
296 tmp = getMaxId(brokerForClass, extentClass, original);
297 }
298 if (tmp > max)
299 {
300 max = tmp;
301 }
302 }
303 }
304 return max;
305 }
306
307
308
309
310
311 public static long getMaxIdForClass(
312 PersistenceBroker brokerForClass, ClassDescriptor cldForOriginalOrExtent, FieldDescriptor original)
313 throws PersistenceBrokerException
314 {
315 FieldDescriptor field = null;
316 if (!original.getClassDescriptor().equals(cldForOriginalOrExtent))
317 {
318
319 if (!original.getClassDescriptor().getFullTableName().equals(
320 cldForOriginalOrExtent.getFullTableName()))
321 {
322
323 field = cldForOriginalOrExtent.getFieldDescriptorByName(original.getAttributeName());
324 }
325 }
326 else
327 {
328 field = original;
329 }
330 if (field == null)
331 {
332
333 return 0;
334 }
335
336 String column = field.getColumnName();
337 long result = 0;
338 ResultSet rs = null;
339 Statement stmt = null;
340 StatementManagerIF sm = brokerForClass.serviceStatementManager();
341 String table = cldForOriginalOrExtent.getFullTableName();
342
343 String sql = SM_SELECT_MAX + column + SM_FROM + table;
344 try
345 {
346
347 stmt = sm.getGenericStatement(cldForOriginalOrExtent, Query.NOT_SCROLLABLE);
348 rs = stmt.executeQuery(sql);
349 rs.next();
350 result = rs.getLong(1);
351 }
352 catch (Exception e)
353 {
354 log.warn("Cannot lookup max value from table " + table + " for column " + column +
355 ", PB was " + brokerForClass + ", using jdbc-descriptor " +
356 brokerForClass.serviceConnectionManager().getConnectionDescriptor(), e);
357 }
358 finally
359 {
360 try
361 {
362 sm.closeResources(stmt, rs);
363 }
364 catch (Exception ignore)
365 {
366
367 }
368 }
369 return result;
370 }
371
372
373
374
375
376
377
378
379
380 public static Long getSeqStart(Properties prop)
381 {
382 String result = prop.getProperty(PROP_SEQ_START, null);
383 if(result == null)
384 {
385 result = prop.getProperty(PROP_SEQ_START_OLD, null);
386 }
387 if(result != null)
388 {
389 return new Long(Long.parseLong(result));
390 }
391 else
392 {
393 return null;
394 }
395 }
396
397
398
399
400
401
402
403
404
405 public static Long getSeqIncrementBy(Properties prop)
406 {
407 String result = prop.getProperty(PROP_SEQ_INCREMENT_BY, null);
408 if(result != null)
409 {
410 return new Long(Long.parseLong(result));
411 }
412 else
413 {
414 return null;
415 }
416 }
417
418
419
420
421
422
423
424
425
426 public static Long getSeqMaxValue(Properties prop)
427 {
428 String result = prop.getProperty(PROP_SEQ_MAX_VALUE, null);
429 if(result != null)
430 {
431 return new Long(Long.parseLong(result));
432 }
433 else
434 {
435 return null;
436 }
437 }
438
439
440
441
442
443
444
445
446
447 public static Long getSeqMinValue(Properties prop)
448 {
449 String result = prop.getProperty(PROP_SEQ_MIN_VALUE, null);
450 if(result != null)
451 {
452 return new Long(Long.parseLong(result));
453 }
454 else
455 {
456 return null;
457 }
458 }
459
460
461
462
463
464
465
466
467
468 public static Long getSeqCacheValue(Properties prop)
469 {
470 String result = prop.getProperty(PROP_SEQ_CACHE, null);
471 if(result != null)
472 {
473 return new Long(Long.parseLong(result));
474 }
475 else
476 {
477 return null;
478 }
479 }
480
481
482
483
484
485
486
487
488
489 public static Boolean getSeqCycleValue(Properties prop)
490 {
491 String result = prop.getProperty(PROP_SEQ_CYCLE, null);
492 if(result != null)
493 {
494 return Boolean.valueOf(result);
495 }
496 else
497 {
498 return null;
499 }
500 }
501
502
503
504
505
506
507
508
509
510 public static Boolean getSeqOrderValue(Properties prop)
511 {
512 String result = prop.getProperty(PROP_SEQ_ORDER, null);
513 if(result != null)
514 {
515 return Boolean.valueOf(result);
516 }
517 else
518 {
519 return null;
520 }
521 }
522
523
524
525
526
527
528
529
530
531 public static String getSeqAsValue(Properties prop)
532 {
533 return prop.getProperty(PROP_SEQ_AS, null);
534 }
535 }