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
45
46 package org.melati.poem.prepro;
47
48 import java.util.Vector;
49 import java.io.StreamTokenizer;
50 import java.io.Writer;
51 import java.io.IOException;
52
53
54
55
56
57
58 public abstract class FieldDef {
59
60 protected final TableDef table;
61
62 protected final String name;
63
64 protected final String capitalisedName;
65
66 protected int displayOrder;
67
68 String displayName;
69
70 String description;
71
72
73 protected final String typeShortName;
74
75 protected final String rawType;
76
77 protected final Vector<FieldQualifier> fieldQualifiers;
78
79 final String shortestUnambiguousClassname;
80
81 final String tableAccessorMethod;
82
83 protected String displayLevel = null;
84
85 protected String searchability = null;
86
87 private boolean sortDescending = false;
88
89 int displayOrderPriority = -1;
90
91 private boolean isNullable = false;
92
93 private boolean isTroidColumn = false;
94
95 private boolean isDeletedColumn = false;
96
97 private boolean isEditable = true;
98
99 private boolean isCreateable = true;
100
101 private boolean isIndexed = false;
102
103 private boolean isUnique = false;
104
105 boolean isCompareOnly = false;
106
107 private int width = -1, height = -1;
108
109 String renderinfo = null;
110
111 protected int lineNumber;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 public FieldDef(int lineNo, TableDef table, String name, String type,
133 String rawType, int displayOrder, Vector<FieldQualifier> qualifiers)
134 throws IllegalityException {
135 this.lineNumber = lineNo;
136 this.table = table;
137 this.name = name;
138 this.displayOrder = displayOrder;
139 this.capitalisedName = StringUtils.capitalised(name);
140 this.typeShortName = type;
141 this.rawType = rawType;
142 this.fieldQualifiers = qualifiers;
143
144 this.shortestUnambiguousClassname = table.tableNamingInfo.mainClassUnambiguous();
145 this.tableAccessorMethod = table.tableNamingInfo.tableAccessorMethod();
146
147 for (int q = 0; q < qualifiers.size(); ++q) {
148 ((FieldQualifier)qualifiers.elementAt(q)).apply(this);
149 }
150
151 }
152
153
154 public String toString() {
155 return table.name + "." + name + " (" + (isNullable ? "nullable " : "")
156 + typeShortName + ")";
157 }
158
159 private static void readFieldQualifiers(Vector<FieldQualifier> qualifiers, StreamTokenizer tokens)
160 throws ParsingDSDException, IOException {
161 while (tokens.ttype == '(') {
162 tokens.nextToken();
163 qualifiers.addElement(FieldQualifier.from(tokens));
164 DSD.expect(tokens, ')');
165 tokens.nextToken();
166 }
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public static FieldDef from(TableDef table, StreamTokenizer tokens,
189 int displayOrder) throws ParsingDSDException, IOException,
190 IllegalityException {
191 table.addImport("org.melati.poem.AccessPoemException", "both");
192 table.addImport("org.melati.poem.ValidationPoemException", "table");
193 table.addImport("org.melati.poem.Persistent", "table");
194
195 table.definesColumns = true;
196 Vector<FieldQualifier> qualifiers = new Vector<FieldQualifier>();
197 readFieldQualifiers(qualifiers, tokens);
198 if (tokens.ttype != StreamTokenizer.TT_WORD)
199 throw new ParsingDSDException("<field type>", tokens);
200 String type = tokens.sval;
201
202 if (type.equals("byte")) {
203 if (tokens.nextToken() != '[' || tokens.nextToken() != ']')
204 throw new ParsingDSDException("[", tokens);
205 type = "byte[]";
206 }
207
208 if (tokens.nextToken() != StreamTokenizer.TT_WORD)
209 throw new ParsingDSDException("<field name>", tokens);
210 String name = tokens.sval;
211 tokens.nextToken();
212 readFieldQualifiers(qualifiers, tokens);
213 DSD.expect(tokens, ';');
214 int lineNo = tokens.lineno();
215 if (type.equals("Integer"))
216 return new IntegerFieldDef(lineNo, table, name, displayOrder, qualifiers);
217 if (type.equals("Long"))
218 return new LongFieldDef(lineNo, table, name, displayOrder, qualifiers);
219 else if (type.equals("Double"))
220 return new DoubleFieldDef(lineNo, table, name, displayOrder, qualifiers);
221 else if (type.equals("Boolean"))
222 return new BooleanFieldDef(lineNo, table, name, displayOrder, qualifiers);
223 else if (type.equals("String"))
224 return new StringFieldDef(lineNo, table, name, displayOrder, qualifiers);
225 else if (type.equals("Password"))
226 return new PasswordFieldDef(lineNo, table, name, displayOrder, qualifiers);
227 else if (type.equals("Date"))
228 return new DateFieldDef(lineNo, table, name, displayOrder, qualifiers);
229 else if (type.equals("Timestamp"))
230 return new TimestampFieldDef(lineNo, table, name, displayOrder,
231 qualifiers);
232 else if (type.equals("Time"))
233 return new TimeFieldDef(lineNo, table, name, displayOrder,
234 qualifiers);
235 else if (type.equals("ColumnType"))
236 return new ColumnTypeFieldDef(lineNo, table, name, displayOrder,
237 qualifiers);
238 else if (type.equals("DisplayLevel"))
239 return new DisplayLevelFieldDef(lineNo, table, name, displayOrder,
240 qualifiers);
241 else if (type.equals("Searchability"))
242 return new SearchabilityFieldDef(lineNo, table, name, displayOrder,
243 qualifiers);
244 else if (type.equals("IntegrityFix"))
245 return new IntegrityFixFieldDef(lineNo, table, name, displayOrder,
246 qualifiers);
247 else if (type.equals("BigDecimal"))
248 return new BigDecimalFieldDef(lineNo, table, name, displayOrder,
249 qualifiers);
250 else if (type.equals("byte[]"))
251 return new BinaryFieldDef(lineNo, table, name, displayOrder, qualifiers);
252 else
253 return new ReferenceFieldDef(lineNo, table, name, displayOrder, type,
254 qualifiers);
255 }
256
257
258
259
260
261
262
263
264
265
266 public void generateBaseMethods(Writer w) throws IOException {
267 w.write("\n /**\n" + " * Retrieves the <code>" + capitalisedName
268 + "</code> value, without locking, \n" + " * for this <code>"
269 + table.nameFromDsd + "</code> <code>Persistent</code>.\n" + " *\n"
270 + " * see org.melati.poem.prepro.FieldDef"
271 + "#generateBaseMethods \n" + " * @return the " + rawType + " " + name
272 + "\n" + " */\n");
273 w.write(" public " + rawType + " get" + capitalisedName + "_unsafe() {\n"
274 + " return " + name + ";\n" + " }\n" + "\n");
275 w.write("\n /**\n" + " * Sets the <code>" + capitalisedName
276 + "</code> value directly, without checking, \n" + " * for this "
277 + table.nameFromDsd + " <code>Persistent</code>.\n" + " * \n"
278 + " * see org.melati.poem.prepro.FieldDef"
279 + "#generateBaseMethods \n"
280 + " * @param cooked the pre-validated value to set\n" + " */\n");
281 w.write(" public void set" + capitalisedName + "_unsafe(" + rawType
282 + " cooked) {\n" + " " + name + " = cooked;\n" + " }\n");
283 }
284
285
286
287
288
289
290
291
292
293 public void generateFieldCreator(Writer w) throws IOException {
294 w.write("\n /**\n"
295 + " * Retrieves the <code>" + capitalisedName + "</code> value as a <code>Field</code>\n"
296 + " * from this <code>" + table.nameFromDsd + "</code> <code>Persistent</code>.\n"
297 + " * \n"
298 + " * see org.melati.poem.prepro.FieldDef#generateFieldCreator \n"
299 + " * @throws AccessPoemException \n"
300 + " * if the current <code>AccessToken</code> \n"
301 + " * does not confer write access rights\n"
302 + " * @return the " + rawType + " " + name + "\n"
303 + " */\n");
304 w.write(" public Field<" + rawType + "> get" + capitalisedName + "Field() throws AccessPoemException {\n"
305 + " Column<"+rawType+"> c = _"+ tableAccessorMethod + "()." + "get" + capitalisedName + "Column();\n"
306 + " return new Field<"+rawType+">(("+rawType+")c.getRaw(this), c);\n"
307 + " }\n");
308 }
309
310
311
312
313
314
315
316
317
318 public abstract void generateJavaDeclaration(Writer w) throws IOException;
319
320
321
322
323
324
325
326
327
328 public void generateColDecl(Writer w) throws IOException {
329
330 w.write("Column<"+rawType+"> col_" + name);
331 }
332
333
334
335
336
337
338
339
340
341 public void generateColAccessor(Writer w) throws IOException {
342 w.write("\n /**\n"
343 + " * Retrieves the <code>" + capitalisedName + "</code> <code>Column</code> for this \n"
344 + " * <code>"+ table.nameFromDsd + "</code> <code>Table</code>.\n" + " * \n"
345 + " * see org.melati.poem.prepro.FieldDef#generateColAccessor \n"
346 + " * @return the " + name + " <code>Column</code>\n"
347 + " */\n");
348 w.write(" public final Column<"+rawType+"> get" + capitalisedName + "Column() {\n"
349 + " return col_" + name + ";\n" + " }\n");
350 }
351
352
353
354
355
356
357
358
359
360
361 protected void generateColRawAccessors(Writer w) throws IOException {
362 w.write(" public Object getRaw_unsafe(Persistent g)\n"
363 + " throws AccessPoemException {\n"
364 + " return ((" + shortestUnambiguousClassname + ")g)." + "get" + capitalisedName
365 + "_unsafe();\n" + " }\n" + "\n");
366
367 w.write(" public void setRaw_unsafe(Persistent g, Object raw)\n"
368 + " throws AccessPoemException {\n" + " (("
369 + shortestUnambiguousClassname + ")g).set" + capitalisedName + "_unsafe((" + rawType + ")raw);\n"
370 + " }\n");
371 }
372
373
374
375
376
377
378
379
380
381
382 public void generateColDefinition(Writer w) throws IOException {
383 w
384 .write(" defineColumn(col_"
385 + name
386 + " =\n"
387 + " new Column<"+rawType +">(this, \""
388 + name
389 + "\",\n"
390 + " "
391 + poemTypeJava()
392 + ",\n"
393 + " DefinitionSource.dsd) { \n"
394 + " public Object getCooked(Persistent g)\n"
395 + " throws AccessPoemException, PoemException {\n"
396 + " return (("
397 + shortestUnambiguousClassname
398 + ")g).get"
399 + capitalisedName
400 + "();\n"
401 + " }\n"
402 + "\n"
403 + " public void setCooked(Persistent g, Object cooked)\n"
404 + " throws AccessPoemException, ValidationPoemException {\n"
405 + " ((" + shortestUnambiguousClassname + ")g).set" + capitalisedName + "((" + typeShortName
406 + ")cooked);\n" + " }\n" + "\n"
407 + " public Field<"+rawType+"> asField(Persistent g) {\n"
408 + " return ((" + shortestUnambiguousClassname + ")g).get" + capitalisedName
409 + "Field();\n" + " }\n" + "\n");
410
411 if (isTroidColumn || !isEditable)
412 w.write(" public boolean defaultUserEditable() {\n"
413 + " return false;\n" + " }\n" + "\n");
414
415 if (isTroidColumn || !isCreateable)
416 w.write(" public boolean defaultUserCreateable() {\n"
417 + " return false;\n" + " }\n" + "\n");
418
419 if (displayLevel != null)
420 w.write(" public DisplayLevel defaultDisplayLevel() {\n"
421 + " return DisplayLevel." + displayLevel + ";\n"
422 + " }\n" + "\n");
423
424 if (searchability != null)
425 w.write(" public Searchability defaultSearchability() {\n"
426 + " return Searchability." + searchability + ";\n"
427 + " }\n" + "\n");
428
429 if (displayOrderPriority != -1)
430 w.write(" public Integer defaultDisplayOrderPriority() {\n"
431 + " return new Integer(" + displayOrderPriority + ");\n"
432 + " }\n" + "\n");
433
434 if (sortDescending)
435 w.write(" public boolean defaultSortDescending() {\n"
436 + " return true;\n" + " }\n" + "\n");
437
438 if (displayName != null)
439 w.write(" public String defaultDisplayName() {\n"
440 + " return " + StringUtils.quoted(displayName, '"')
441 + ";\n" + " }\n" + "\n");
442
443 w
444 .write(" public int defaultDisplayOrder() {\n"
445 + " return " + displayOrder + ";\n" + " }\n"
446 + "\n");
447
448 if (description != null)
449 w.write(" public String defaultDescription() {\n"
450 + " return " + StringUtils.quoted(description, '"')
451 + ";\n" + " }\n" + "\n");
452
453 if (isIndexed)
454 w.write(" public boolean defaultIndexed() {\n"
455 + " return true;\n" + " }\n" + "\n");
456
457 if (isUnique)
458 w.write(" public boolean defaultUnique() {\n"
459 + " return true;\n" + " }\n" + "\n");
460
461 if (width != -1)
462 w.write(" public int defaultWidth() {\n"
463 + " return " + width + ";\n" + " }\n" + "\n");
464
465 if (height != -1)
466 w.write(" public int defaultHeight() {\n"
467 + " return " + height + ";\n" + " }\n" + "\n");
468
469 if (renderinfo != null)
470 w.write(" public String defaultRenderinfo() {\n"
471 + " return " + StringUtils.quoted(renderinfo, '"') + ";\n"
472 + " }\n" + "\n");
473
474 generateColRawAccessors(w);
475
476 w.write(" });\n");
477 }
478
479
480 public abstract String poemTypeJava();
481
482
483
484
485 public boolean isDeletedColumn() {
486 return isDeletedColumn;
487 }
488
489
490
491
492
493
494 public void setDeletedColumn(boolean isDeletedColumn) {
495 if (this.isDeletedColumn)
496 throw new IllegalityException(lineNumber,
497 "Deleted qualifier already set true.");
498 this.isDeletedColumn = isDeletedColumn;
499 }
500
501
502
503
504 public boolean isTroidColumn() {
505 return isTroidColumn;
506 }
507
508
509
510
511
512
513 public void setTroidColumn(boolean isTroidColumn) {
514 if (this.isTroidColumn)
515 throw new IllegalityException(lineNumber,
516 "Troid qualifier already set true.");
517 this.isTroidColumn = isTroidColumn;
518 }
519
520
521
522
523 public boolean isNullable() {
524 return isNullable;
525 }
526
527
528
529
530
531
532 public void setNullable(boolean isNullable) {
533 if (this.isNullable)
534 throw new IllegalityException(lineNumber,
535 "Nullable qualifier already set true.");
536 this.isNullable = isNullable;
537 }
538
539
540
541
542 public boolean isEditable() {
543 return isEditable;
544 }
545
546
547
548
549
550
551 public void setEditable(boolean isEditable) {
552 if (!this.isEditable)
553 throw new IllegalityException(lineNumber,
554 "Editable qualifier already set true.");
555 this.isEditable = isEditable;
556 }
557
558
559
560
561 public boolean isSortDescending() {
562 return sortDescending;
563 }
564
565
566
567
568
569
570 public void setSortDescending(boolean sortDescending) {
571 if (this.sortDescending)
572 throw new IllegalityException(lineNumber,
573 "Sort descending qualifier already set true.");
574 this.sortDescending = sortDescending;
575 }
576
577
578
579
580 public boolean isCreateable() {
581 return isCreateable;
582 }
583
584
585
586
587
588
589 public void setCreateable(boolean isCreateable) {
590 if (!this.isCreateable)
591 throw new IllegalityException(lineNumber,
592 "Creatable qualifier already set true.");
593 this.isCreateable = isCreateable;
594 }
595
596
597
598
599 public boolean isIndexed() {
600 return isIndexed;
601 }
602
603
604
605
606
607 public void setIndexed(boolean isIndexed) {
608 if (this.isIndexed)
609 throw new IllegalityException(lineNumber,
610 "Indexed qualifier already set true.");
611 this.isIndexed = isIndexed;
612 }
613
614
615
616
617 public boolean isUnique() {
618 return isUnique;
619 }
620
621
622
623
624
625
626 public void setUnique(boolean isUnique) {
627 if (this.isUnique)
628 throw new IllegalityException(lineNumber,
629 "Unique qualifier already set true.");
630 this.isUnique = isUnique;
631 }
632
633
634
635
636 public int getWidth() {
637 return width;
638 }
639
640
641
642
643
644
645 public void setWidth(int width) {
646 if (this.width != -1)
647 throw new IllegalityException(lineNumber, "Size already set to "
648 + this.width + " cannot overwrite with " + width);
649 this.width = width;
650 }
651
652
653
654
655 public int getHeight() {
656 return height;
657 }
658
659
660
661
662
663
664 public void setHeight(int height) {
665 if (this.height != -1)
666 throw new IllegalityException(lineNumber, "Height already set to "
667 + this.width + " cannot overwrite with " + width);
668 this.height = height;
669 }
670 }