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