1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.common.ui.client.configurable.mvc.sections;
17
18 import java.util.ArrayList;
19 import java.util.HashSet;
20 import java.util.List;
21
22 import org.kuali.student.common.assembly.data.Data;
23 import org.kuali.student.common.assembly.data.Data.Key;
24 import org.kuali.student.common.assembly.data.QueryPath;
25 import org.kuali.student.common.ui.client.application.Application;
26 import org.kuali.student.common.ui.client.configurable.mvc.CanProcessValidationResults;
27 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
28 import org.kuali.student.common.ui.client.configurable.mvc.LayoutController;
29 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBinding;
30 import org.kuali.student.common.ui.client.configurable.mvc.ValidationEventBindingImpl;
31 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBinding;
32 import org.kuali.student.common.ui.client.configurable.mvc.binding.ModelWidgetBindingSupport;
33 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityComposite;
34 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroup;
35 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityGroupItem;
36 import org.kuali.student.common.ui.client.configurable.mvc.multiplicity.MultiplicityItem;
37 import org.kuali.student.common.ui.client.event.ContentDirtyEvent;
38 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
39 import org.kuali.student.common.ui.client.mvc.Callback;
40 import org.kuali.student.common.ui.client.mvc.Controller;
41 import org.kuali.student.common.ui.client.mvc.DataModel;
42 import org.kuali.student.common.ui.client.mvc.HasCrossConstraints;
43 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
44 import org.kuali.student.common.ui.client.mvc.View;
45 import org.kuali.student.common.ui.client.widgets.field.layout.element.AbbrPanel;
46 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
47 import org.kuali.student.common.ui.client.widgets.field.layout.element.SpanPanel;
48 import org.kuali.student.common.ui.client.widgets.field.layout.layouts.FieldLayout;
49 import org.kuali.student.common.validation.dto.ValidationResultInfo;
50 import org.kuali.student.common.validation.dto.ValidationResultInfo.ErrorLevel;
51
52 import com.google.gwt.core.client.GWT;
53 import com.google.gwt.user.client.ui.Widget;
54
55
56
57
58
59
60 public abstract class BaseSection extends SpanPanel implements Section{
61
62 protected FieldLayout layout;
63
64 protected ArrayList<Section> sections = new ArrayList<Section>();
65 protected ArrayList<FieldDescriptor> fields = new ArrayList<FieldDescriptor>();
66 protected LayoutController layoutController = null;
67 protected boolean isValidationEnabled = true;
68 protected boolean isDirty = false;
69
70
71
72
73
74
75
76
77
78
79
80
81
82 @Override
83 public String addField(final FieldDescriptor fieldDescriptor) {
84 String key = null;
85
86 if (fieldDescriptor.isVisible()){
87 fields.add(fieldDescriptor);
88 key = layout.addField(fieldDescriptor.getFieldElement());
89
90 ValidationEventBinding binding = new ValidationEventBindingImpl();
91 if(fieldDescriptor.getValidationRequestCallback()== null){
92 fieldDescriptor.setValidationCallBack(new Callback<Boolean>() {
93 @Override
94 public void exec(Boolean result) {
95 final ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
96 if (mwb != null) {
97 final Widget w = fieldDescriptor.getFieldWidget();
98 final String modelId = fieldDescriptor.getModelId();
99 final Controller parent;
100 Controller findResult = LayoutController.findParentLayout(w);
101 if(BaseSection.this instanceof View){
102 findResult = ((View)BaseSection.this).getController();
103 }
104 parent = findResult;
105 if(parent != null){
106 if (modelId == null) {
107 parent.requestModel(new ModelRequestCallback<DataModel>() {
108
109 @Override
110 public void onModelReady(DataModel model) {
111 validateField(fieldDescriptor, model, parent);
112
113
114 HashSet<HasCrossConstraints> fds = Application.getApplicationContext().getCrossConstraint(null, Application.getApplicationContext().getParentPath()+fieldDescriptor.getFieldKey());
115 if(fds!=null){
116 for(HasCrossConstraints fd:fds){
117 fd.reprocessWithUpdatedConstraints();
118 }
119 }
120 }
121
122 @Override
123 public void onRequestFail(Throwable cause) {
124 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
125 }
126
127 });
128 } else {
129 parent.requestModel(modelId, new ModelRequestCallback<DataModel>() {
130
131 @Override
132 public void onModelReady(DataModel model) {
133 validateField(fieldDescriptor, model, parent);
134 }
135
136 @Override
137 public void onRequestFail(Throwable cause) {
138 GWT.log("Unable to retrieve model to validate " + fieldDescriptor.getFieldKey(), null);
139 }
140
141 }); }
142 }
143 } else {
144 GWT.log(fieldDescriptor.getFieldKey() + " has no widget binding.", null);
145 }
146 }
147 });
148 }
149 binding.bind(fieldDescriptor);
150 }
151
152 return key;
153 }
154
155 private void validateField(
156 final FieldDescriptor fieldDescriptor, final DataModel model, Controller controller) {
157 Widget w = fieldDescriptor.getFieldWidget();
158 ModelWidgetBinding mwb = fieldDescriptor.getModelWidgetBinding();
159 if(fieldDescriptor.getFieldKey() != null){
160 mwb.setModelValue(w, model, fieldDescriptor.getFieldKey());
161 dirtyCheckField(fieldDescriptor, model);
162 ValidateRequestEvent e = new ValidateRequestEvent();
163 e.setFieldDescriptor(fieldDescriptor);
164 e.setValidateSingleField(true);
165 controller.fireApplicationEvent(e);
166 }
167 }
168
169 private void dirtyCheckField(FieldDescriptor fieldDescriptor, DataModel model){
170 QueryPath fieldPath = QueryPath.parse(fieldDescriptor.getFieldKey());
171 QueryPath qPathDirty = fieldPath.subPath(0, fieldPath.size() - 1);
172 qPathDirty.add(ModelWidgetBindingSupport.RUNTIME_ROOT);
173 qPathDirty.add(ModelWidgetBindingSupport.DIRTY_PATH);
174 qPathDirty.add(fieldPath.get(fieldPath.size()-1));
175 Boolean dirty = false;
176
177 if(ensureDirtyFlagPath(model.getRoot(), qPathDirty)){
178 dirty = model.get(qPathDirty);
179 }
180 if(dirty){
181 setIsDirty(true);
182 fieldDescriptor.setDirty(true);
183 }
184 }
185
186 protected boolean ensureDirtyFlagPath(Data root, QueryPath path) {
187 Data current = root;
188 boolean containsFlag = false;
189 for (int i = 0; i < path.size(); i++) {
190 Key key = path.get(i);
191 if(i == path.size() - 1){
192 containsFlag = current.containsKey(key);
193 break;
194 }
195 Data d = current.get(key);
196 if (d == null) {
197 containsFlag = false;
198 break;
199 }
200 current = d;
201 }
202 return containsFlag;
203 }
204
205
206
207
208
209
210 @Override
211 public String addSection(Section section) {
212
213 section.setLayoutController(layoutController);
214 sections.add(section);
215 String key = layout.addLayout(section.getLayout());
216 return key;
217 }
218
219
220
221
222
223
224 @Override
225 public void removeSection(Section section){
226 sections.remove(section);
227 layout.removeLayoutElement(section.getLayout());
228 }
229
230
231
232
233
234 protected void clearValidation() {
235 layout.clearValidation();
236
237 }
238
239
240
241
242
243
244 @Override
245 public List<FieldDescriptor> getFields() {
246 List<FieldDescriptor> allFields = new ArrayList<FieldDescriptor>();
247 allFields.addAll(fields);
248
249 for(Section ns: sections){
250 allFields.addAll(ns.getFields());
251 }
252 return allFields;
253 }
254
255
256
257
258
259 @Override
260 public List<FieldDescriptor> getUnnestedFields() {
261 return fields;
262 }
263
264
265
266
267
268 @Override
269 public List<Section> getSections() {
270 return sections;
271 }
272
273
274
275
276
277
278
279 @Override
280 public ErrorLevel processValidationResults(List<ValidationResultInfo> results, boolean clearAllValidation){
281 if(clearAllValidation){
282 this.clearValidation();
283 }
284 ErrorLevel status = ErrorLevel.OK;
285
286 if (isValidationEnabled){
287
288 for(FieldDescriptor f: this.fields){
289
290 if(f.hasHadFocus()){
291 for(ValidationResultInfo vr: results){
292 String vrElement = vr.getElement();
293 if(vrElement.startsWith("/")){
294 vrElement = vrElement.substring(1);
295 }
296 if(vrElement.equals(f.getFieldKey())){
297 FieldElement element = f.getFieldElement();
298 if (element != null){
299 ErrorLevel fieldStatus = element.processValidationResult(vr);
300 if(fieldStatus.getLevel() > status.getLevel()){
301 status = fieldStatus;
302 }
303 }
304 }
305 }
306 }
307
308 if(f.getFieldWidget() instanceof MultiplicityComposite ){
309 MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
310
311
312 for(MultiplicityItem item: mc.getItems()){
313 if(item.getItemWidget() instanceof Section && !item.isDeleted()){
314 ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearAllValidation);
315 if(fieldStatus.getLevel() > status.getLevel()){
316 status = fieldStatus;
317 }
318 }
319 }
320 }
321
322 if(f.getFieldWidget() instanceof MultiplicityGroup ){
323 MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
324
325
326 for(MultiplicityGroupItem item: mg.getItems()){
327 if(item.getItemWidget() instanceof Section && !item.isDeleted()){
328 ErrorLevel fieldStatus = ((Section)item.getItemWidget()).processValidationResults(results, clearAllValidation);
329 if(fieldStatus.getLevel() > status.getLevel()){
330 status = fieldStatus;
331 }
332 }
333 }
334 }
335 if (f.getFieldWidget() instanceof CanProcessValidationResults) {
336 ErrorLevel fieldStatus = ((CanProcessValidationResults) f.getFieldWidget()).processValidationResults(f, results, clearAllValidation);
337 if (fieldStatus.getLevel() > status.getLevel()) {
338 status = fieldStatus;
339 }
340 }
341 }
342
343 for(Section s: sections){
344 ErrorLevel subsectionStatus = s.processValidationResults(results,clearAllValidation);
345 if(subsectionStatus.getLevel() > status.getLevel()){
346 status = subsectionStatus;
347 }
348 }
349 }
350
351 return status;
352 }
353
354
355
356
357
358 @Override
359 public ErrorLevel processValidationResults(List<ValidationResultInfo> results) {
360 return processValidationResults(results, true);
361 }
362
363
364
365
366
367
368 @Override
369 public LayoutController getLayoutController() {
370 return this.layoutController;
371 }
372
373 @Override
374 public void setLayoutController(LayoutController controller) {
375 this.layoutController = controller;
376 }
377
378
379
380
381
382
383 @Override
384 public String addWidget(Widget w) {
385 return layout.addWidget(w);
386 }
387
388
389
390
391
392
393
394 public void setFieldHasHadFocusFlags(boolean hadFocus) {
395 for(FieldDescriptor f: fields){
396 f.setHasHadFocus(hadFocus);
397 if(f.getFieldWidget() instanceof MultiplicityComposite){
398 MultiplicityComposite mc = (MultiplicityComposite) f.getFieldWidget();
399
400 for(MultiplicityItem item: mc.getItems()){
401 if(item.getItemWidget() instanceof Section && !item.isDeleted()){
402 ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
403 }
404 }
405 }else if(f.getFieldWidget() instanceof MultiplicityGroup){
406 MultiplicityGroup mg = (MultiplicityGroup) f.getFieldWidget();
407
408 for(MultiplicityGroupItem item: mg.getItems()){
409 if(item.getItemWidget() instanceof Section && !item.isDeleted()){
410 ((Section) item.getItemWidget()).setFieldHasHadFocusFlags(hadFocus);
411 }
412 }
413 }
414 }
415
416 for(Section s: sections){
417 s.setFieldHasHadFocusFlags(hadFocus);
418 }
419
420 }
421
422
423
424
425
426 @Override
427 public void enableValidation(boolean enableValidation) {
428 this.isValidationEnabled = enableValidation;
429 }
430
431 @Override
432 public boolean isValidationEnabled() {
433 return isValidationEnabled;
434 }
435
436
437
438
439
440
441
442 @Override
443 public void updateModel(DataModel model){
444 SectionBinding.INSTANCE.setModelValue(this, model, "");
445 }
446
447
448
449
450
451
452
453
454
455 @Override
456 public void updateWidgetData(DataModel model) {
457 SectionBinding.INSTANCE.setWidgetValue(this, model, "");
458 }
459
460
461
462
463
464 @Override
465 public void resetFieldInteractionFlags() {
466 this.isDirty = false;
467 for(FieldDescriptor f: fields){
468 f.setDirty(false);
469 f.setHasHadFocus(false);
470 }
471
472 for(Section s: sections){
473 s.resetFieldInteractionFlags();
474 }
475
476 }
477
478 @Override
479 public void resetDirtyFlags() {
480 this.isDirty = false;
481 for(FieldDescriptor f: fields){
482 f.setDirty(false);
483 }
484
485 for(Section s: sections){
486 s.resetDirtyFlags();
487 }
488 }
489
490
491
492
493
494
495
496 @Override
497 public String addSection(String key, Section section) {
498 sections.add(section);
499 section.getLayout().setKey(key);
500 String rkey = layout.addLayout(section.getLayout());
501 return rkey;
502 }
503
504 @Override
505 public FieldDescriptor getField(String fieldKey) {
506 for(FieldDescriptor f: fields){
507 if(f.getFieldKey().equals(fieldKey)){
508 return f;
509 }
510 }
511 return null;
512 }
513
514
515
516
517
518
519
520 @Override
521 public FieldLayout getLayout() {
522 return layout;
523 }
524
525 @Override
526 public Section getSection(String sectionKey) {
527 for(Section s: sections){
528 if(s.getLayout().getKey().equals(sectionKey)){
529 return s;
530 }
531 }
532 return null;
533 }
534
535 @Override
536 public void removeField(String fieldKey) {
537 int index = 0;
538 boolean found = false;
539 for(FieldDescriptor f: fields){
540 if(f.getFieldKey().equals(fieldKey)){
541 index = fields.indexOf(f);
542 found = true;
543 break;
544 }
545 }
546 if(found){
547 fields.remove(index);
548 }
549 layout.removeLayoutElement(fieldKey);
550
551 }
552
553 @Override
554 public void removeField(FieldDescriptor field) {
555
556 fields.remove(field);
557 layout.removeLayoutElement(field.getFieldKey());
558
559 }
560
561 @Override
562 public void removeSection(String sectionKey) {
563 int index = 0;
564 boolean found = false;
565 for(Section s: sections){
566 if(s.getLayout().getKey().equals(sectionKey)){
567 index = sections.indexOf(s);
568 found = true;
569 break;
570 }
571 }
572 if(found){
573 sections.remove(index);
574 }
575 layout.removeLayoutElement(sectionKey);
576
577 }
578
579 @Override
580 public void removeWidget(Widget widget) {
581 layout.removeLayoutElement(widget);
582
583 }
584
585 @Override
586 public void removeWidget(String key) {
587 layout.removeLayoutElement(key);
588
589 }
590
591
592
593
594
595
596
597 public boolean isDirty(){
598 if(!this.isDirty){
599
600 for(Section s: sections){
601 if(s.isDirty()){
602 setIsDirty(true);
603 break;
604 }
605 }
606 }
607 return isDirty;
608 }
609
610 public void setIsDirty(boolean state) {
611
612 if (layoutController == null){
613 layoutController = LayoutController.findParentLayout(layout);
614 }
615 if (isDirty != state){
616 isDirty = state;
617 if (layoutController != null && isDirty){
618 layoutController.fireApplicationEvent(new ContentDirtyEvent());
619 }
620 }
621 }
622
623
624
625
626 @Override
627 public void add(Widget w) {
628 super.add(w);
629 }
630
631
632
633
634
635 @Override
636 public void addStyleName(String style) {
637 layout.addStyleName(style);
638 }
639
640 @Override
641 public void setStyleName(String style) {
642 layout.setStyleName(style);
643 }
644
645
646
647
648
649 public void setInstructions(String html){
650 layout.setInstructions(html);
651 }
652
653
654
655
656
657 public void setHelp(String html){
658 layout.setHelp(html);
659 }
660
661
662
663
664
665 public void setRequired(AbbrPanel required){
666 layout.setRequired(required);
667 }
668 }