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.admin;
47
48 import java.util.Vector;
49 import java.util.Enumeration;
50
51 import org.melati.Melati;
52 import org.melati.servlet.FormDataAdaptor;
53 import org.melati.servlet.InvalidUsageException;
54 import org.melati.servlet.Form;
55 import org.melati.servlet.TemplateServlet;
56 import org.melati.template.ServletTemplateContext;
57 import org.melati.template.FormParameterException;
58
59 import org.melati.poem.AccessToken;
60 import org.melati.poem.AccessPoemException;
61 import org.melati.poem.BaseFieldAttributes;
62 import org.melati.poem.Capability;
63 import org.melati.poem.Column;
64 import org.melati.poem.ColumnInfo;
65 import org.melati.poem.ColumnInfoTable;
66 import org.melati.poem.ColumnTypePoemType;
67 import org.melati.poem.Database;
68 import org.melati.poem.DeletionIntegrityPoemException;
69 import org.melati.poem.DisplayLevel;
70 import org.melati.poem.ExecutingSQLPoemException;
71 import org.melati.poem.Field;
72 import org.melati.poem.Initialiser;
73 import org.melati.poem.Persistent;
74 import org.melati.poem.PoemException;
75 import org.melati.poem.PoemThread;
76 import org.melati.poem.PoemType;
77 import org.melati.poem.PoemTypeFactory;
78 import org.melati.poem.ReferencePoemType;
79 import org.melati.poem.Setting;
80 import org.melati.poem.Table;
81 import org.melati.poem.TableInfo;
82 import org.melati.poem.TableInfoTable;
83 import org.melati.poem.ValidationPoemException;
84
85 import org.melati.util.CountedDumbPagedEnumeration;
86 import org.melati.poem.util.EnumUtils;
87 import org.melati.poem.util.MappedEnumeration;
88 import org.melati.util.MelatiBugMelatiException;
89 import org.melati.util.MelatiRuntimeException;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 public class Admin extends TemplateServlet {
127 private static final long serialVersionUID = 1L;
128
129 private static String screenStylesheetURL = null;
130 private static String primaryDisplayTable = null;
131 private static String homepageURL = null;
132
133
134
135
136 protected static Persistent create(Table table,
137 final ServletTemplateContext context) {
138 Persistent result = table.create(new Initialiser() {
139 public void init(Persistent object) throws AccessPoemException,
140 ValidationPoemException {
141 Form.extractFields(context, object);
142 }
143 });
144 result.postEdit(true);
145 return result;
146 }
147
148
149
150
151 protected static final String adminTemplate(String name) {
152 return "org/melati/admin/" + name;
153 }
154
155
156
157
158 protected static String dsdTemplate(ServletTemplateContext context) {
159
160
161
162
163
164 String c = PoemThread.database().getClass().getName();
165 int dot = c.lastIndexOf('.');
166 String p = c.substring(0, dot);
167
168 context.put("package", p);
169 return adminTemplate("DSD");
170 }
171
172
173
174
175 protected static String primarySelectTemplate(ServletTemplateContext context,
176 Melati melati) throws PoemException {
177 final Table table = melati.getTable();
178
179 Field primaryCriterion;
180
181 Column column = table.primaryCriterionColumn();
182 if (column != null) {
183 String sea = context.getForm("field_" + column.getName());
184 primaryCriterion = new Field(
185 sea == null ?
186 (
187 melati.getObject() == null ?
188 null : column.getRaw(melati.getObject()))
189 : column.getType().rawOfString(sea),
190 new BaseFieldAttributes(column,column.getType().withNullable(true)));
191 } else
192 primaryCriterion = null;
193
194 context.put("primaryCriterion", primaryCriterion);
195 return adminTemplate("PrimarySelect");
196 }
197
198
199
200
201
202 protected static String selectionTemplate(ServletTemplateContext context,
203 Melati melati) {
204 String templateName = context.getForm("template");
205 if (templateName == null) {
206 selection(context, melati, true);
207 return adminTemplate("Selection");
208 } else {
209 selection(context, melati, false);
210 return adminTemplate(templateName);
211 }
212 }
213
214
215
216
217
218
219
220 protected static String selectionRightTemplate(
221 ServletTemplateContext context, Melati melati) {
222 selection(context, melati, true);
223 context.put("inRight", Boolean.TRUE);
224 return adminTemplate("Selection");
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 protected static ServletTemplateContext selection(
245 ServletTemplateContext context, Melati melati, boolean paged) {
246 final Table table = melati.getTable();
247
248 final Database database = table.getDatabase();
249
250
251
252 final Persistent criteria = table.newPersistent();
253
254 Vector whereClause = new Vector();
255
256 for (Enumeration c = table.columns(); c.hasMoreElements();) {
257 Column column = (Column) c.nextElement();
258 String name = "field_" + column.getName();
259 String fieldValue = Form.getFieldNulled(context, name);
260 if (fieldValue != null) {
261 column
262 .setRaw_unsafe(criteria, column.getType().rawOfString(fieldValue));
263
264
265 whereClause.addElement(name + "=" + melati.urlEncode(fieldValue));
266 }
267 }
268
269 context.put("whereClause", EnumUtils.concatenated("&", whereClause
270 .elements()));
271
272
273
274 PoemType searchColumnsType = getSearchColumnsType(database, table);
275
276 Vector orderings = new Vector();
277 Vector orderClause = new Vector();
278
279
280 for (int o = 1; o <= table.displayColumnsCount(DisplayLevel.summary); ++o) {
281 String name = "field_order-" + o;
282 String orderColumnIDString = Form.getFieldNulled(context, name);
283 Integer orderColumnID = null;
284
285 if (orderColumnIDString != null) {
286 String toggleName = "field_order-" + o + "-toggle";
287 String orderColumnSortOrderToggle = Form.getFieldNulled(context,
288 toggleName);
289 Boolean toggle = new Boolean(orderColumnSortOrderToggle);
290 orderColumnID = (Integer) searchColumnsType
291 .rawOfString(orderColumnIDString);
292 ColumnInfo info = (ColumnInfo) searchColumnsType
293 .cookedOfRaw(orderColumnID);
294 String desc = Boolean.TRUE.equals(info.getSortdescending()) ? (Boolean.TRUE
295 .equals(toggle) ? "" : " DESC")
296 : (Boolean.TRUE.equals(toggle) ? " DESC" : "");
297 orderings.addElement(database.quotedName(info.getName()) + desc);
298 orderClause.addElement(name + "=" + orderColumnIDString);
299 }
300 }
301
302 String orderBySQL = null;
303 if (orderings.elements().hasMoreElements())
304 orderBySQL = EnumUtils.concatenated(", ", orderings.elements());
305 context.put("orderClause", EnumUtils.concatenated("&", orderClause
306 .elements()));
307
308 int start = 0;
309 String startString = Form.getFieldNulled(context, "start");
310 if (startString != null) {
311 try {
312 start = Math.max(0, Integer.parseInt(startString));
313 } catch (NumberFormatException e) {
314 throw new MelatiBugMelatiException("How did you get that in there?",
315 new FormParameterException("start", "Param must be an Integer"));
316 }
317 }
318 if (paged) {
319 final int resultsPerPage = 20;
320 context.put("results",
321 new CountedDumbPagedEnumeration(
322 table.selection(criteria, orderBySQL, false, false),
323 start, resultsPerPage,
324 table.cachedCount(criteria, false, false).count())
325 );
326 } else {
327 context.put("results", table.selection(criteria, orderBySQL, false, false));
328 }
329 return context;
330 }
331
332
333
334
335 protected static String popupSelectTemplate(ServletTemplateContext context,
336 Melati melati) throws PoemException {
337 popupSelect(context, melati);
338 return adminTemplate("PopupSelect");
339 }
340
341 protected static ServletTemplateContext popupSelect(ServletTemplateContext context,
342 Melati melati) throws PoemException {
343 final Table table = melati.getTable();
344
345 final Database database = table.getDatabase();
346
347
348
349 final Persistent criteria = table.newPersistent();
350
351 MappedEnumeration criterias = new MappedEnumeration(table
352 .getSearchCriterionColumns()) {
353 public Object mapped(Object c) {
354 return ((Column) c).asField(criteria).withNullable(true);
355 }
356 };
357
358 context.put("criteria", EnumUtils.vectorOf(criterias));
359 PoemType searchColumnsType = getSearchColumnsType(database, table);
360
361 Vector orderings = new Vector();
362
363 Enumeration searchColumns = searchColumnsType.possibleRaws();
364 int o = 0;
365 while (searchColumns.hasMoreElements()) {
366 String name = "order-" + o++;
367 orderings.addElement(new Field(searchColumns.nextElement(),
368 new BaseFieldAttributes(name, searchColumnsType)));
369 }
370
371 context.put("orderings", orderings);
372
373 return context;
374 }
375
376
377
378
379 private static PoemType getSearchColumnsType(final Database database, final Table table) {
380 PoemType searchColumnsType = new ReferencePoemType(database
381 .getColumnInfoTable(), false) {
382 protected Enumeration _possibleRaws() {
383 return new MappedEnumeration(table.getSearchCriterionColumns()) {
384 public Object mapped(Object column) {
385 return ((Column) column).getColumnInfo().getTroid();
386 }
387 };
388 }
389 };
390 return searchColumnsType;
391 }
392
393
394
395
396 protected static String selectionWindowPrimarySelectTemplate(
397 ServletTemplateContext context, Melati melati) throws PoemException {
398 context.put("inPopup", Boolean.TRUE);
399 return primarySelectTemplate(context, melati);
400 }
401
402
403
404
405 protected static String selectionWindowSelectionTemplate(
406 ServletTemplateContext context, Melati melati) {
407 selection(context, melati, true);
408 context.put("inPopup", Boolean.TRUE);
409 return adminTemplate("Selection");
410 }
411
412
413
414
415
416
417
418
419
420
421
422 protected static String addTemplate(final ServletTemplateContext context,
423 Melati melati) throws PoemException {
424
425
426
427
428
429
430
431
432
433
434
435 Enumeration columns = melati.getTable().getDetailDisplayColumns();
436 Vector fields = new Vector();
437 while (columns.hasMoreElements()) {
438 Column column = (Column) columns.nextElement();
439 String stringValue = context.getForm("field_" + column.getName());
440 Object value = null;
441 if (stringValue != null)
442 value = column.getType().rawOfString(stringValue);
443 else if (column.getType() instanceof ColumnTypePoemType)
444 value = PoemTypeFactory.STRING.getCode();
445 fields.add(new Field(value, column));
446 }
447 if (melati.getTable() instanceof TableInfoTable) {
448 Database database = melati.getDatabase();
449
450
451
452
453 final int troidHeight = 1;
454 final int troidWidth = 20;
455 Field troidNameField = new Field("id", new BaseFieldAttributes(
456 "troidName", "Troid column", "Name of TROID column", database
457 .getColumnInfoTable().getNameColumn().getType(), troidWidth,
458 troidHeight, null, false, true, true));
459
460 fields.add(troidNameField);
461 }
462 context.put("fields", fields.elements());
463 return adminTemplate("Add");
464 }
465
466
467
468
469
470
471
472
473 protected static String addUpdateTemplate(ServletTemplateContext context,
474 Melati melati) throws PoemException {
475
476 Persistent newPersistent = create(melati.getTable(), context);
477
478 if (melati.getTable() instanceof TableInfoTable)
479 melati.getDatabase().addTableAndCommit((TableInfo) newPersistent,
480 context.getForm("field_troidName"));
481 if (melati.getTable() instanceof ColumnInfoTable)
482 ((ColumnInfo) newPersistent).getTableinfo().actualTable()
483 .addColumnAndCommit((ColumnInfo) newPersistent);
484
485 context.put("object", newPersistent);
486 return adminTemplate("Updated");
487 }
488
489
490
491
492
493
494
495
496 protected static String updateTemplate(ServletTemplateContext context,
497 Melati melati) throws PoemException {
498 Persistent object = melati.getObject();
499 object.preEdit();
500 Form.extractFields(context, object);
501 object.postEdit(false);
502 return adminTemplate("Updated");
503 }
504
505 protected static String deleteTemplate(ServletTemplateContext context,
506 Melati melati) throws PoemException {
507 try {
508 if (melati.getTable().getName().equals("tableinfo")) {
509 TableInfo tableInfo = (TableInfo) melati.getObject();
510 melati.getDatabase().deleteTableAndCommit(tableInfo);
511 } else if (melati.getTable().getName().equals("columninfo")) {
512 ColumnInfo columnInfo = (ColumnInfo) melati.getObject();
513 columnInfo.getTableinfo().actualTable().deleteColumnAndCommit(
514 columnInfo);
515 } else
516 melati.getObject().delete();
517
518 return adminTemplate("Updated");
519 } catch (DeletionIntegrityPoemException e) {
520 context.put("object", e.object);
521 context.put("references", e.references);
522 context.put("returnURL", melati.getSameURL() + "?action=Delete");
523 return adminTemplate("DeleteFailure");
524 }
525 }
526
527 protected static String duplicateTemplate(ServletTemplateContext context,
528 Melati melati) throws PoemException {
529 Persistent dup = melati.getObject().duplicated();
530 Form.extractFields(context, dup);
531 try {
532 dup.getTable().create(dup);
533 } catch (ExecutingSQLPoemException e) {
534 throw new NonUniqueKeyValueAnticipatedException(e);
535 }
536 context.put("object", dup);
537 return adminTemplate("Updated");
538 }
539
540
541
542
543
544
545
546
547
548
549 protected static String modifyTemplate(ServletTemplateContext context,
550 Melati melati) throws FormParameterException {
551 String action = melati.getRequest().getParameter("action");
552 if ("Update".equals(action))
553 return updateTemplate(context, melati);
554 if ("Delete".equals(action))
555 return deleteTemplate(context, melati);
556 if ("Duplicate".equals(action))
557 return duplicateTemplate(context, melati);
558 else
559 throw new MelatiBugMelatiException("How did you get that in there?",
560 new FormParameterException(
561 "action", "Bad action from Edit: " + action));
562 }
563
564 protected static String uploadTemplate(ServletTemplateContext context)
565 throws PoemException {
566 context.put("field", context.getForm("field"));
567 return adminTemplate("Upload");
568 }
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583 protected static String uploadDoneTemplate(ServletTemplateContext context)
584 throws PoemException {
585 String field = context.getForm("field");
586 context.put("field", field);
587 String url = "";
588 url = context.getMultipartForm("file").getDataURL();
589 if (url == null)
590 throw new NullUrlDataAdaptorException(context.getMultipartForm("file").getFormDataAdaptor());
591 context.put("url", url);
592 return adminTemplate("UploadDone");
593 }
594
595 static class NullUrlDataAdaptorException extends MelatiRuntimeException {
596 private static final long serialVersionUID = 1L;
597 private FormDataAdaptor fda;
598 NullUrlDataAdaptorException(FormDataAdaptor fda) {
599 this.fda = fda;
600 }
601
602
603 public String getMessage() {
604 return "The configured FormDataAdaptor (" + fda.getClass().getName() + ") returns a null URL.";
605 }
606 }
607
608 protected static String setupTemplate(ServletTemplateContext context,
609 Melati melati) {
610 screenStylesheetURL = melati.getDatabase().getSettingTable().ensure(
611 Admin.class.getName() + ".ScreenStylesheetURL", "/blue.css",
612 "ScreenStylesheetURL",
613 "path to stylesheet, relative to melati-static, starting with a slash")
614 .getValue();
615 primaryDisplayTable = melati.getDatabase().getSettingTable().ensure(
616 Admin.class.getName() + ".PrimaryDisplayTable", "setting",
617 "PrimaryDisplayTable", "The default table to display").getValue();
618 Setting homepageURLSetting = melati.getDatabase().getSettingTable().ensure(
619 Admin.class.getName() + ".HomepageURL", "http://www.melati.org/",
620 "HomepageURL", "The home page for this database");
621 homepageURL = homepageURLSetting.getValue();
622
623 context.put("object", homepageURLSetting);
624 return adminTemplate("Updated");
625 }
626
627 protected String doTemplateRequest(Melati melati,
628 ServletTemplateContext context) throws Exception {
629
630 if (Form.getField(context, "goto", null) != null)
631 melati.getResponse().sendRedirect(Form.getField(context, "goto", null));
632
633 melati.setPassbackExceptionHandling();
634 melati.setResponseContentType("text/html");
635
636 Capability admin = PoemThread.database().getCanAdminister();
637 AccessToken token = PoemThread.accessToken();
638 if (!token.givesCapability(admin))
639 throw new AccessPoemException(token, admin);
640
641 context.put("admin", new AdminUtils(melati));
642
643 if (melati.getMethod() == null)
644 return adminTemplate("Main");
645 if (melati.getMethod().equals("blank"))
646 return adminTemplate("blank");
647 if (melati.getMethod().equals("setup"))
648 return setupTemplate(context, melati);
649 if (melati.getMethod().equals("Main"))
650 return adminTemplate("Main");
651 if (melati.getMethod().equals("Top"))
652 return adminTemplate("Top");
653 if (melati.getMethod().equals("UploadDone"))
654 return uploadDoneTemplate(context);
655 if (melati.getMethod().equals("Record"))
656 return adminTemplate("Record");
657 if (melati.getMethod().equals("Selection"))
658 return selectionTemplate(context, melati);
659
660 if (melati.getObject() != null) {
661 if (melati.getMethod().equals("Update"))
662 return modifyTemplate(context, melati);
663 if (melati.getObject() instanceof AdminSpecialised) {
664 String templateName = ((AdminSpecialised) melati.getObject())
665 .adminHandle(melati, melati.getMarkupLanguage());
666 if (templateName != null)
667 return templateName;
668 }
669 }
670
671 if (melati.getTable() != null) {
672 if (melati.getMethod().equals("Tree"))
673 return adminTemplate("Tree");
674 if (melati.getMethod().equals("Bottom"))
675 return adminTemplate("Bottom");
676 if (melati.getMethod().equals("Table"))
677 return adminTemplate("Table");
678 if (melati.getMethod().equals("PrimarySelect"))
679 return primarySelectTemplate(context, melati);
680 if (melati.getMethod().equals("EditHeader"))
681 return adminTemplate("EditHeader");
682 if (melati.getMethod().equals("Edit"))
683 return adminTemplate("Edit");
684 if (melati.getMethod().equals("Upload"))
685 return uploadTemplate(context);
686
687 if (melati.getMethod().equals("SelectionRight"))
688 return selectionRightTemplate(context, melati);
689 if (melati.getMethod().equals("Navigation"))
690 return adminTemplate("Navigation");
691 if (melati.getMethod().equals("PopUp"))
692 return popupSelectTemplate(context, melati);
693 if (melati.getMethod().equals("SelectionWindow"))
694 return adminTemplate("SelectionWindow");
695 if (melati.getMethod().equals("SelectionWindowPrimarySelect"))
696 return selectionWindowPrimarySelectTemplate(context, melati);
697 if (melati.getMethod().equals("SelectionWindowSelection"))
698 return selectionWindowSelectionTemplate(context, melati);
699 if (melati.getMethod().equals("Add"))
700 return addTemplate(context, melati);
701 if (melati.getMethod().equals("Created"))
702 return addUpdateTemplate(context, melati);
703 }
704 if (melati.getMethod().equals("DSD"))
705 return dsdTemplate(context);
706
707 throw new InvalidUsageException(this, melati.getPoemContext());
708 }
709
710
711
712
713 static String getScreenStylesheetURL() {
714 return screenStylesheetURL;
715 }
716
717
718
719
720 static void setScreenStylesheetURL(String screenStylesheetURL) {
721 Admin.screenStylesheetURL = screenStylesheetURL;
722 }
723
724
725
726
727 static String getPrimaryDisplayTable() {
728 return primaryDisplayTable;
729 }
730
731
732
733
734 static void setPrimaryDisplayTable(String primaryDisplayTable) {
735 Admin.primaryDisplayTable = primaryDisplayTable;
736 }
737
738
739
740
741 static String getHomepageURL() {
742 return homepageURL;
743 }
744
745
746
747
748 static void setHomepageURL(String homepageURL) {
749 Admin.homepageURL = homepageURL;
750 }
751 }