1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.service.impl;
17
18 import com.google.common.collect.Sets;
19 import org.apache.commons.lang.ObjectUtils;
20 import org.apache.commons.lang.StringUtils;
21 import org.apache.log4j.Logger;
22 import org.kuali.rice.core.api.CoreApiServiceLocator;
23 import org.kuali.rice.core.api.config.property.ConfigurationService;
24 import org.kuali.rice.core.api.util.RiceKeyConstants;
25 import org.kuali.rice.core.api.util.io.SerializationUtils;
26 import org.kuali.rice.kim.api.identity.Person;
27 import org.kuali.rice.krad.bo.PersistableBusinessObjectBaseAdapter;
28 import org.kuali.rice.krad.data.DataObjectService;
29 import org.kuali.rice.krad.data.DataObjectWrapper;
30 import org.kuali.rice.krad.data.KradDataServiceLocator;
31 import org.kuali.rice.krad.inquiry.Inquirable;
32 import org.kuali.rice.krad.messages.MessageService;
33 import org.kuali.rice.krad.service.DataDictionaryService;
34 import org.kuali.rice.krad.service.KRADServiceLocator;
35 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
36 import org.kuali.rice.krad.service.LegacyDataAdapter;
37 import org.kuali.rice.krad.service.ModuleService;
38 import org.kuali.rice.krad.uif.UifConstants;
39 import org.kuali.rice.krad.uif.UifPropertyPaths;
40 import org.kuali.rice.krad.uif.component.BindingInfo;
41 import org.kuali.rice.krad.uif.component.Component;
42 import org.kuali.rice.krad.uif.component.PropertyReplacer;
43 import org.kuali.rice.krad.uif.component.RequestParameter;
44 import org.kuali.rice.krad.uif.container.CollectionGroup;
45 import org.kuali.rice.krad.uif.container.Container;
46 import org.kuali.rice.krad.uif.field.DataField;
47 import org.kuali.rice.krad.uif.layout.LayoutManager;
48 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
49 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
50 import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
51 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
52 import org.kuali.rice.krad.uif.service.ViewHelperService;
53 import org.kuali.rice.krad.uif.util.BooleanMap;
54 import org.kuali.rice.krad.uif.util.CopyUtils;
55 import org.kuali.rice.krad.uif.util.LifecycleElement;
56 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
57 import org.kuali.rice.krad.uif.util.RecycleUtils;
58 import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
59 import org.kuali.rice.krad.uif.view.ExpressionEvaluatorFactory;
60 import org.kuali.rice.krad.uif.view.RequestAuthorizationCache;
61 import org.kuali.rice.krad.uif.view.View;
62 import org.kuali.rice.krad.uif.view.ViewAuthorizer;
63 import org.kuali.rice.krad.uif.view.ViewModel;
64 import org.kuali.rice.krad.uif.view.ViewPresentationController;
65 import org.kuali.rice.krad.uif.widget.Inquiry;
66 import org.kuali.rice.krad.util.ErrorMessage;
67 import org.kuali.rice.krad.util.GlobalVariables;
68 import org.kuali.rice.krad.util.GrowlMessage;
69 import org.kuali.rice.krad.util.KRADConstants;
70 import org.kuali.rice.krad.util.KRADUtils;
71 import org.kuali.rice.krad.util.MessageMap;
72 import org.kuali.rice.krad.valuefinder.ValueFinder;
73 import org.kuali.rice.krad.web.form.UifFormBase;
74 import org.kuali.rice.krad.web.service.impl.CollectionControllerServiceImpl.CollectionActionParameters;
75 import org.springframework.beans.PropertyAccessorUtils;
76
77 import java.io.Serializable;
78 import java.lang.annotation.Annotation;
79 import java.lang.reflect.Field;
80 import java.text.MessageFormat;
81 import java.util.ArrayList;
82 import java.util.Collection;
83 import java.util.Collections;
84 import java.util.HashMap;
85 import java.util.HashSet;
86 import java.util.LinkedList;
87 import java.util.List;
88 import java.util.Map;
89 import java.util.Map.Entry;
90 import java.util.Queue;
91 import java.util.Set;
92
93
94
95
96
97
98 public class ViewHelperServiceImpl implements ViewHelperService, Serializable {
99 private static final long serialVersionUID = 1772618197133239852L;
100 private static final Logger LOG = Logger.getLogger(ViewHelperServiceImpl.class);
101
102 private transient ConfigurationService configurationService;
103 private transient DataDictionaryService dataDictionaryService;
104 private transient LegacyDataAdapter legacyDataAdapter;
105 private transient DataObjectService dataObjectService;
106 private transient ViewDictionaryService viewDictionaryService;
107 private transient ExpressionEvaluatorFactory expressionEvaluatorFactory;
108
109
110
111
112 @Override
113 public void addCustomContainerComponents(ViewModel model, Container container) {
114
115 }
116
117
118
119
120
121
122
123 public void buildInquiryLink(Object dataObject, String propertyName, Inquiry inquiry) {
124 Inquirable inquirable = getViewDictionaryService().getInquirable(dataObject.getClass(), inquiry.getViewName());
125 if (inquirable != null) {
126 inquirable.buildInquirableLink(dataObject, propertyName, inquiry);
127 } else {
128
129
130
131 inquiry.setRender(false);
132 }
133 }
134
135
136
137
138 @Override
139 public void performCustomApplyModel(LifecycleElement element, Object model) {
140
141 }
142
143
144
145
146 @Override
147 public void performCustomFinalize(LifecycleElement element, Object model, LifecycleElement parent) {
148
149 }
150
151
152
153
154 @Override
155 public void performCustomInitialization(LifecycleElement element) {
156
157 }
158
159
160
161
162 @Override
163 public void performCustomViewFinalize(Object model) {
164
165 }
166
167
168
169
170 @Override
171 public void performCustomViewInitialization(Object model) {
172
173 }
174
175
176
177
178 @Override
179 public void processAfterAddLine(ViewModel model, Object lineObject, String collectionId, String collectionPath,
180 boolean isValidLine) {
181
182 }
183
184
185
186
187 @Override
188 public void processAfterDeleteLine(ViewModel model, String collectionId, String collectionPath, int lineIndex) {
189
190 }
191
192
193
194
195 @Override
196 public void processAfterSaveLine(ViewModel model, Object lineObject, String collectionId, String collectionPath) {
197
198 }
199
200
201
202
203 @Override
204 public void processBeforeAddLine(ViewModel model, Object addLine, String collectionId, String collectionPath) {
205
206 }
207
208
209
210
211 @Override
212 public void processBeforeSaveLine(ViewModel model, Object lineObject, String collectionId, String collectionPath) {
213
214 }
215
216
217
218
219 @Override
220 public void processBeforeEditLine(ViewModel model, Object lineObject, String collectionId, String collectionPath) {
221
222 }
223
224
225
226
227 @Override
228 public void processAfterEditLine(ViewModel model, Object lineObject, String collectionId, String collectionPath) {
229
230 }
231
232
233
234
235 @SuppressWarnings("unchecked")
236 @Override
237 public void processCollectionAddBlankLine(ViewModel model, String collectionId, String collectionPath) {
238 if (!(model instanceof ViewModel)) {
239 return;
240 }
241
242 ViewModel viewModel = (ViewModel) model;
243
244 if (collectionId == null) {
245 logAndThrowRuntime(
246 "Unable to get collection group component for Id: " + collectionPath + " path: " + collectionPath);
247 }
248
249
250 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
251 if (collection == null) {
252 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
253 }
254
255 Class<?> collectionObjectClass = (Class<?>) viewModel.getViewPostMetadata().getComponentPostData(collectionId,
256 UifConstants.PostMetadata.COLL_OBJECT_CLASS);
257 Object newLine = KRADUtils.createNewObjectFromClass(collectionObjectClass);
258
259 List<Object> lineDataObjects = new ArrayList<Object>();
260 lineDataObjects.add(newLine);
261 viewModel.getViewPostMetadata().getAddedCollectionObjects().put(collectionId, lineDataObjects);
262 processAndAddLineObject(viewModel, newLine, collectionId, collectionPath);
263 }
264
265
266
267
268 @SuppressWarnings("unchecked")
269 @Override
270 public void processCollectionAddLine(ViewModel model, String collectionId, String collectionPath) {
271
272 BindingInfo addLineBindingInfo = (BindingInfo) model.getViewPostMetadata().getComponentPostData(
273 collectionId, UifConstants.PostMetadata.ADD_LINE_BINDING_INFO);
274 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLineBindingInfo.getBindingPath());
275 if (addLine == null) {
276 logAndThrowRuntime("Add line instance not found for path: " + addLineBindingInfo.getBindingPath());
277 }
278
279 processAndAddLineObject(model, addLine, collectionId, collectionPath);
280 }
281
282
283
284
285
286
287
288
289
290
291 public void processAndAddLineObject(ViewModel viewModel, Object newLine, String collectionId, String collectionPath) {
292 String addLinePlacement = (String) viewModel.getViewPostMetadata().getComponentPostData(collectionId, UifConstants.PostMetadata.ADD_LINE_PLACEMENT);
293
294
295 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(viewModel, collectionPath);
296 if (collection == null) {
297 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
298 }
299
300 processBeforeAddLine(viewModel, newLine, collectionId, collectionPath);
301
302 boolean isValidLine = performAddLineValidation(viewModel, newLine, collectionId, collectionPath);
303 if (isValidLine) {
304
305
306
307 List<Object> lineDataObjects = new ArrayList<Object>();
308 viewModel.getViewPostMetadata().getAddedCollectionObjects().put(collectionId, lineDataObjects);
309
310 int addedIndex = addLine(collection, newLine, addLinePlacement.equals("TOP"));
311
312
313
314 boolean linkToAddedCollection = linkAddedLine(viewModel, collectionPath, addedIndex);
315
316 if (viewModel instanceof UifFormBase && linkToAddedCollection) {
317 KRADServiceLocatorWeb.getLegacyDataAdapter().refreshAllNonUpdatingReferences(newLine);
318 ((UifFormBase) viewModel).getAddedCollectionItems().add(newLine);
319 }
320 processAfterAddLine(viewModel, newLine, collectionId, collectionPath, isValidLine);
321 }
322 }
323
324
325
326
327 @Override
328 public void processCollectionDeleteLine(ViewModel model, String collectionId, String collectionPath,
329 int lineIndex) {
330
331 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
332 if (collection == null) {
333 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
334 }
335
336
337
338 if (collection instanceof List) {
339 Object deleteLine = ((List<Object>) collection).get(lineIndex);
340
341
342 boolean isValid = performDeleteLineValidation(model, collectionId, collectionPath, deleteLine);
343 if (isValid) {
344 ((List<Object>) collection).remove(lineIndex);
345
346 String collectionLabel = (String) model.getViewPostMetadata().getComponentPostData(collectionId,
347 UifConstants.PostMetadata.COLL_LABEL);
348 GlobalVariables.getMessageMap().putInfoForSectionId(collectionId,
349 RiceKeyConstants.MESSAGE_COLLECTION_LINE_DELETED, collectionLabel);
350
351 processAfterDeleteLine(model, collectionId, collectionPath, lineIndex);
352 }
353 } else {
354 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
355 }
356 }
357
358
359
360
361 @Override
362 public void processCollectionRetrieveEditLineDialog(ViewModel model, String collectionId, String collectionPath,
363 int selectedLineIndex) {
364 String objectPath = collectionPath + "[" + selectedLineIndex + "]";
365
366
367 Object dataObject = ObjectPropertyUtils.getPropertyValue(model, objectPath);
368 if (dataObject == null) {
369 logAndThrowRuntime("Unable to get collection property from model for path: " + objectPath);
370 }
371
372
373 if (((UifFormBase) model).getDialogDataObject() == null) {
374 ((UifFormBase) model).setDialogDataObject(SerializationUtils.deepCopy((Serializable) dataObject));
375 }
376 }
377
378
379
380
381 @Override
382 public void processCollectionEditLine(ViewModel model, CollectionActionParameters parameterData) {
383 String collectionId = parameterData.getSelectedCollectionId();
384 String collectionPath = parameterData.getSelectedCollectionPath();
385 int selectedLineIndex = parameterData.getSelectedLineIndex();
386
387
388 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
389 if (collection == null) {
390 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
391 }
392
393
394 if (collection instanceof List) {
395 Object editLine = ((List<Object>) collection).get(selectedLineIndex);
396 Object dialogDataObject = ((UifFormBase) model).getDialogDataObject();
397
398 if (dialogDataObject != null) {
399 editLine = SerializationUtils.deepCopy((Serializable) dialogDataObject);
400 ((UifFormBase) model).setDialogDataObject(null);
401 }
402
403 processBeforeEditLine(model, editLine, collectionId, collectionPath);
404
405 ((List<Object>) collection).remove(selectedLineIndex);
406 ((List<Object>) collection).add(selectedLineIndex, editLine);
407
408 processAfterEditLine(model, editLine, collectionId, collectionPath);
409
410 } else {
411 logAndThrowRuntime("Only List collection implementations are supported for the edit by index method");
412 }
413 }
414
415
416
417
418 @Override
419 public void processCollectionCloseEditLineDialog(ViewModel model, String collectionId, String collectionPath,
420 int selectedLineIndex) {
421 String objectPath = collectionPath + "[" + selectedLineIndex + "]";
422
423
424 Object dataObject = ObjectPropertyUtils.getPropertyValue(model, objectPath);
425 if (dataObject == null) {
426 logAndThrowRuntime("Unable to get collection property from model for path: " + objectPath);
427 }
428 ((UifFormBase) model).setDialogDataObject(null);
429 }
430
431
432
433
434 @Override
435 public void processCollectionSaveLine(ViewModel model, CollectionActionParameters parameterData) {
436 String collectionId = parameterData.getSelectedCollectionId();
437 String collectionPath = parameterData.getSelectedCollectionPath();
438 int selectedLineIndex = parameterData.getSelectedLineIndex();
439
440 Map<String, String[]> parameters = parameterData.getParameters();
441 final ViewPostMetadata viewPostMetadata = model.getViewPostMetadata();
442 BindingInfo addLineBindingInfo = (BindingInfo) viewPostMetadata.getComponentPostData(collectionId, UifConstants.PostMetadata.BINDING_INFO);
443 List<Object> collection = ObjectPropertyUtils.getPropertyValue(model, addLineBindingInfo.getBindingPath());
444
445 Object saveLine = extractNewValuesAndAssign(collectionPath, selectedLineIndex, parameters, collection);
446
447 processBeforeSaveLine(model, saveLine, collectionId, collectionPath);
448 boolean isValidLine = performAddLineValidation(model, saveLine, collectionId, collectionPath);
449 if (isValidLine) {
450 collection.set(selectedLineIndex, saveLine);
451 KRADServiceLocatorWeb.getLegacyDataAdapter().refreshAllNonUpdatingReferences(saveLine);
452 processAfterSaveLine(model, saveLine, collectionId, collectionPath);
453 }
454 }
455
456
457
458
459
460
461
462
463
464
465 protected Object extractNewValuesAndAssign(String collectionPath, int selectedLineIndex, Map<String, String[]> parameters, List<Object> collection) {
466 String[] fieldList = new String[]{"field1", "field2", "field3", "field4", "field5", "field6"};
467 Object saveLine = collection.get(selectedLineIndex);
468 for(String field : fieldList){
469 String index = String.format("%s[%s].%s", collectionPath, selectedLineIndex, field);
470 String fieldValue = extractSingleValue(parameters.get(index));
471 setValue(saveLine, field, fieldValue);
472 }
473 return saveLine;
474 }
475
476
477
478
479
480
481
482
483 private void setValue(Object object, String fieldName, Object value){
484 try {
485 Class<?> clazz = object.getClass();
486 Field field = clazz.getDeclaredField(fieldName);
487 field.setAccessible(true);
488 field.set(object, value);
489 } catch(Exception e){
490 LOG.error("Unable to access private variable "+fieldName+" in object " + object.getClass()+". " + e.getMessage());
491 }
492 }
493
494
495
496
497
498
499 protected String extractSingleValue(String[] data){
500 if (data == null) return null;
501 if (data.length < 1) return null;
502 return data[0];
503 }
504
505
506
507
508 @SuppressWarnings("unchecked")
509 public void processMultipleValueLookupResults(ViewModel model, String collectionId, String collectionPath,
510 String multiValueReturnFields, String lookupResultValues) {
511
512 if (StringUtils.isBlank(lookupResultValues) || !(model instanceof ViewModel)) {
513 return;
514 }
515
516 ViewModel viewModel = (ViewModel) model;
517
518 if (StringUtils.isBlank(collectionId)) {
519 throw new RuntimeException(
520 "Id is not set for this collection lookup: " + collectionId + ", " + "path: " + collectionPath);
521 }
522
523
524 Class<?> collectionObjectClass = (Class<?>) viewModel.getViewPostMetadata().getComponentPostData(collectionId,
525 UifConstants.PostMetadata.COLL_OBJECT_CLASS);
526 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
527 if (collection == null) {
528 Class<?> collectionClass = ObjectPropertyUtils.getPropertyType(model, collectionPath);
529 collection = (Collection<Object>) KRADUtils.createNewObjectFromClass(collectionClass);
530 ObjectPropertyUtils.setPropertyValue(model, collectionPath, collection);
531 }
532
533
534 Map<String, String> fieldConversions =
535 (Map<String, String>) viewModel.getViewPostMetadata().getComponentPostData(collectionId,
536 UifConstants.PostMetadata.COLL_LOOKUP_FIELD_CONVERSIONS);
537
538
539 Map <String, String> returnedFieldConversions = filterByReturnedFieldConversions(multiValueReturnFields,
540 fieldConversions);
541
542 List<String> toFieldNamesColl = new ArrayList<String>(returnedFieldConversions.values());
543 Collections.sort(toFieldNamesColl);
544 String[] toFieldNames = new String[toFieldNamesColl.size()];
545 toFieldNamesColl.toArray(toFieldNames);
546
547
548 String[] lineValues = StringUtils.split(lookupResultValues, ",");
549
550 List<Object> lineDataObjects = new ArrayList<Object>();
551
552 for (String lineValue : lineValues) {
553 Object lineDataObject = null;
554
555
556 ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
557 collectionObjectClass);
558 if (moduleService != null && moduleService.isExternalizable(collectionObjectClass)) {
559 lineDataObject = moduleService.createNewObjectFromExternalizableClass(collectionObjectClass.asSubclass(
560 org.kuali.rice.krad.bo.ExternalizableBusinessObject.class));
561 } else {
562 lineDataObject = KRADUtils.createNewObjectFromClass(collectionObjectClass);
563 }
564
565 String[] fieldValues = StringUtils.splitByWholeSeparatorPreserveAllTokens(lineValue, ":");
566 if (fieldValues.length != toFieldNames.length) {
567 throw new RuntimeException(
568 "Value count passed back from multi-value lookup does not match field conversion count");
569 }
570
571
572 for (int i = 0; i < fieldValues.length; i++) {
573 String fieldName = toFieldNames[i];
574 ObjectPropertyUtils.setPropertyValue(lineDataObject, fieldName, fieldValues[i]);
575 }
576
577 lineDataObjects.add(lineDataObject);
578 processAndAddLineObject(viewModel, lineDataObject, collectionId, collectionPath);
579 }
580
581 viewModel.getViewPostMetadata().getAddedCollectionObjects().put(collectionId, lineDataObjects);
582 }
583
584
585
586
587
588
589
590
591
592
593
594 protected int addLine(Collection<Object> collection, Object addLine, boolean insertFirst) {
595 int index = -1;
596 if (insertFirst && (collection instanceof List)) {
597 ((List<Object>) collection).add(0, addLine);
598 index = 0;
599 } else {
600 boolean added = collection.add(addLine);
601 if (added) {
602 index = collection.size() - 1;
603 }
604 }
605 return index;
606 }
607
608
609
610
611
612
613
614
615
616 protected boolean linkAddedLine(Object model, String collectionPath, int addedIndex) {
617 int lastSepIndex = PropertyAccessorUtils.getLastNestedPropertySeparatorIndex(collectionPath);
618 if (lastSepIndex != -1) {
619 String collectionParentPath = collectionPath.substring(0, lastSepIndex);
620 Object parent = ObjectPropertyUtils.getPropertyValue(model, collectionParentPath);
621 if (parent != null && getDataObjectService().supports(parent.getClass())) {
622 DataObjectWrapper<?> wrappedParent = getDataObjectService().wrap(parent);
623 String collectionName = collectionPath.substring(lastSepIndex + 1);
624 wrappedParent.linkChanges(Sets.newHashSet(collectionName + "[" + addedIndex + "]"));
625 }
626
627
628
629 if (collectionParentPath.equalsIgnoreCase(UifPropertyPaths.DIALOG_DATA_OBJECT)) {
630 ((UifFormBase) model).setDialogDataObject(parent);
631 return false;
632 }
633 }
634 return true;
635 }
636
637
638
639
640
641
642
643
644
645 protected boolean performAddLineValidation(ViewModel viewModel, Object newLine, String collectionId,
646 String collectionPath) {
647 boolean isValid = true;
648
649 Collection<Object> collectionItems = ObjectPropertyUtils.getPropertyValue(viewModel, collectionPath);
650
651 if (viewModel.getViewPostMetadata().getComponentPostData(collectionId,
652 UifConstants.PostMetadata.DUPLICATE_LINE_PROPERTY_NAMES) == null) {
653 return isValid;
654 }
655
656 List<String> duplicateLinePropertyNames = (List<String>) viewModel.getViewPostMetadata().getComponentPostData(
657 collectionId, UifConstants.PostMetadata.DUPLICATE_LINE_PROPERTY_NAMES);
658
659 String collectionLabel = null;
660 if (viewModel.getViewPostMetadata().getComponentPostData(collectionId, UifConstants.PostMetadata.COLL_LABEL)
661 != null) {
662 collectionLabel = (String) viewModel.getViewPostMetadata().getComponentPostData(collectionId,
663 UifConstants.PostMetadata.COLL_LABEL);
664 }
665
666 String duplicateLineLabelString = null;
667 if (viewModel.getViewPostMetadata().getComponentPostData(collectionId,
668 UifConstants.PostMetadata.DUPLICATE_LINE_LABEL_STRING) != null) {
669 duplicateLineLabelString = (String) viewModel.getViewPostMetadata().getComponentPostData(collectionId,
670 UifConstants.PostMetadata.DUPLICATE_LINE_LABEL_STRING);
671 }
672
673 if (containsDuplicateLine(newLine, collectionItems, duplicateLinePropertyNames)) {
674 isValid = false;
675 String propertyId = UifPropertyPaths.NEW_COLLECTION_LINES + "['" + collectionPath + "']." +
676 duplicateLinePropertyNames.get(0);
677 GlobalVariables.getMessageMap().putError(propertyId, RiceKeyConstants.ERROR_DUPLICATE_ELEMENT,
678 collectionLabel, duplicateLineLabelString);
679 }
680
681 return isValid;
682 }
683
684
685
686
687
688
689
690 protected Map<String, String> filterByReturnedFieldConversions(String multiValueReturnFields,
691 Map<String, String> fieldConversions) {
692
693 Map <String, String> returnedFieldConversions = new HashMap<String, String>();
694 returnedFieldConversions.putAll(fieldConversions);
695
696
697 String[] returnedFieldsStrArr = StringUtils.split(multiValueReturnFields, ",");
698
699 if (returnedFieldsStrArr != null && returnedFieldsStrArr.length > 0) {
700 returnedFieldConversions.clear();
701 for (String fieldConversion : returnedFieldsStrArr) {
702 if (fieldConversions.containsKey(fieldConversion)) {
703 returnedFieldConversions.put(fieldConversion, fieldConversions.get(fieldConversion));
704 }
705 }
706 }
707
708 return returnedFieldConversions;
709 }
710
711
712
713
714
715
716
717
718
719
720 protected boolean containsDuplicateLine(Object addLine, Collection<Object> collectionItems,
721 List<String> duplicateLinePropertyNames) {
722 if (collectionItems.isEmpty() || duplicateLinePropertyNames.isEmpty()) {
723 return false;
724 }
725
726 for (Object collectionItem : collectionItems) {
727 if (isDuplicateLine(addLine, collectionItem, duplicateLinePropertyNames)) {
728 return true;
729 }
730 }
731
732 return false;
733 }
734
735
736
737
738
739
740
741
742
743
744 protected boolean isDuplicateLine(Object addLine, Object collectionItem, List<String> duplicateLinePropertyNames) {
745 if (duplicateLinePropertyNames.isEmpty()) {
746 return false;
747 }
748
749 for (String duplicateLinePropertyName : duplicateLinePropertyNames) {
750 Object addLinePropertyValue = ObjectPropertyUtils.getPropertyValue(addLine, duplicateLinePropertyName);
751 Object duplicateLinePropertyValue = ObjectPropertyUtils.getPropertyValue(collectionItem,
752 duplicateLinePropertyName);
753
754 if (!ObjectUtils.equals(addLinePropertyValue, duplicateLinePropertyValue)) {
755 return false;
756 }
757 }
758
759 return true;
760 }
761
762
763
764
765
766
767
768
769
770
771 protected boolean performDeleteLineValidation(ViewModel model, String collectionId, String collectionPath,
772 Object deleteLine) {
773 return true;
774 }
775
776
777
778
779 @Override
780 public void applyDefaultValuesForCollectionLine(CollectionGroup collectionGroup, Object line) {
781
782 List<DataField> dataFields = ViewLifecycleUtils.getElementsOfTypeDeep(collectionGroup.getAddLineItems(),
783 DataField.class);
784 for (DataField dataField : dataFields) {
785 String bindingPath = "";
786 if (StringUtils.isNotBlank(dataField.getBindingInfo().getBindByNamePrefix())) {
787 bindingPath = dataField.getBindingInfo().getBindByNamePrefix() + ".";
788 }
789 bindingPath += dataField.getBindingInfo().getBindingName();
790
791 populateDefaultValueForField(line, dataField, bindingPath);
792 }
793 }
794
795
796
797
798 @Override
799 public void applyDefaultValues(Component component) {
800 if (component == null) {
801 return;
802 }
803
804 View view = ViewLifecycle.getView();
805 Object model = ViewLifecycle.getModel();
806
807 @SuppressWarnings("unchecked") Queue<LifecycleElement> elementQueue = RecycleUtils.getInstance(
808 LinkedList.class);
809 elementQueue.offer(component);
810 try {
811 while (!elementQueue.isEmpty()) {
812 LifecycleElement currentElement = elementQueue.poll();
813
814
815 if (currentElement instanceof DataField) {
816 DataField dataField = ((DataField) currentElement);
817
818
819 dataField.getBindingInfo().setDefaults(view, dataField.getPropertyName());
820
821 populateDefaultValueForField(model, dataField, dataField.getBindingInfo().getBindingPath());
822 }
823
824 elementQueue.addAll(ViewLifecycleUtils.getElementsForLifecycle(currentElement).values());
825 }
826 } finally {
827 elementQueue.clear();
828 RecycleUtils.recycle(elementQueue);
829 }
830 }
831
832
833
834
835 @Override
836 public void populateViewFromRequestParameters(Map<String, String> parameters) {
837 View view = ViewLifecycle.getView();
838
839
840
841 Map<String, Set<PropertyReplacer>> viewPropertyReplacers = new HashMap<String, Set<PropertyReplacer>>();
842 List<PropertyReplacer> propertyReplacerSource = view.getPropertyReplacers();
843 if (propertyReplacerSource != null) {
844 for (PropertyReplacer replacer : propertyReplacerSource) {
845 String replacerPropertyName = replacer.getPropertyName();
846 Set<PropertyReplacer> propertyReplacers = viewPropertyReplacers.get(replacerPropertyName);
847
848 if (propertyReplacers == null) {
849 viewPropertyReplacers.put(replacerPropertyName,
850 propertyReplacers = new HashSet<PropertyReplacer>());
851 }
852
853 propertyReplacers.add(replacer);
854 }
855 }
856
857 Map<String, Annotation> annotatedFields = CopyUtils.getFieldsWithAnnotation(view.getClass(),
858 RequestParameter.class);
859
860
861
862 Map<String, String> viewRequestParameters = new HashMap<String, String>();
863 for (String fieldToPopulate : annotatedFields.keySet()) {
864 RequestParameter requestParameter = (RequestParameter) annotatedFields.get(fieldToPopulate);
865
866
867 String requestParameterName = requestParameter.parameterName();
868 if (StringUtils.isBlank(requestParameterName)) {
869 requestParameterName = fieldToPopulate;
870 }
871
872 if (!parameters.containsKey(requestParameterName)) {
873 continue;
874 }
875
876 String fieldValue = parameters.get(requestParameterName);
877 if (StringUtils.isNotBlank(fieldValue)) {
878 viewRequestParameters.put(requestParameterName, fieldValue);
879 ObjectPropertyUtils.setPropertyValue(view, fieldToPopulate, fieldValue);
880
881
882
883 if (view.getPropertyExpressions().containsKey(fieldToPopulate)) {
884 view.getPropertyExpressions().remove(fieldToPopulate);
885 }
886
887 if (viewPropertyReplacers.containsKey(fieldToPopulate)) {
888 Set<PropertyReplacer> propertyReplacers = viewPropertyReplacers.get(fieldToPopulate);
889 for (PropertyReplacer replacer : propertyReplacers) {
890 view.getPropertyReplacers().remove(replacer);
891 }
892 }
893 }
894 }
895
896 view.setViewRequestParameters(viewRequestParameters);
897 }
898
899
900
901
902 @Override
903 public String buildGrowlScript() {
904 View view = ViewLifecycle.getView();
905 String growlScript = "";
906
907 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
908
909 MessageMap messageMap = GlobalVariables.getMessageMap();
910 for (GrowlMessage growl : messageMap.getGrowlMessages()) {
911 if (view.isGrowlMessagingEnabled()) {
912 String message = messageService.getMessageText(growl.getNamespaceCode(), growl.getComponentCode(),
913 growl.getMessageKey());
914
915 if (StringUtils.isNotBlank(message)) {
916 if (growl.getMessageParameters() != null) {
917 message = message.replace("'", "''");
918 message = MessageFormat.format(message, (Object[]) growl.getMessageParameters());
919 }
920
921
922 message = message.replace("'", "\\'");
923
924 String title = growl.getTitle();
925 if (StringUtils.isNotBlank(growl.getTitleKey())) {
926 title = messageService.getMessageText(growl.getNamespaceCode(), growl.getComponentCode(),
927 growl.getTitleKey());
928 }
929 title = title.replace("'", "\\'");
930
931 growlScript =
932 growlScript + "showGrowl('" + message + "', '" + title + "', '" + growl.getTheme() + "');";
933 }
934 } else {
935 ErrorMessage infoMessage = new ErrorMessage(growl.getMessageKey(), growl.getMessageParameters());
936 infoMessage.setNamespaceCode(growl.getNamespaceCode());
937 infoMessage.setComponentCode(growl.getComponentCode());
938
939 messageMap.putInfoForSectionId(KRADConstants.GLOBAL_INFO, infoMessage);
940 }
941 }
942
943 return growlScript;
944 }
945
946
947
948
949 @Override
950 public void populateDefaultValueForField(Object object, DataField dataField, String bindingPath) {
951
952 try{
953 if (!ObjectPropertyUtils.isReadableProperty(object, bindingPath) || !ObjectPropertyUtils.isWritableProperty(
954 object, bindingPath)) {
955 return;
956 }
957 }catch(RuntimeException e){
958
959
960
961
962
963 LOG.warn("No property with binding path '" +bindingPath+"' is readable on '"+object+"'"+e.getMessage() );
964 return;
965 }
966
967
968 if (ObjectPropertyUtils.getPropertyValue(object, bindingPath) != null) {
969 return;
970 }
971
972 Object defaultValue = getDefaultValueForField(object, dataField);
973
974 if (defaultValue != null) {
975 ObjectPropertyUtils.setPropertyValue(object, bindingPath, defaultValue);
976 }
977 }
978
979
980
981
982 @Override
983 public Object getDefaultValueForField(Object object, DataField dataField) {
984 View view = ViewLifecycle.getView();
985 Object defaultValue = null;
986
987
988 if (dataField.getDefaultValue() != null && !(dataField.getDefaultValue() instanceof String && StringUtils
989 .isBlank((String) dataField.getDefaultValue()))) {
990 defaultValue = dataField.getDefaultValue();
991 } else if ((dataField.getExpressionGraph() != null) && dataField.getExpressionGraph().containsKey(
992 UifConstants.ComponentProperties.DEFAULT_VALUE)) {
993 defaultValue = dataField.getExpressionGraph().get(UifConstants.ComponentProperties.DEFAULT_VALUE);
994 } else if (dataField.getDefaultValueFinderClass() != null) {
995 ValueFinder defaultValueFinder = KRADUtils.createNewObjectFromClass(dataField.getDefaultValueFinderClass());
996
997 defaultValue = defaultValueFinder.getValue();
998 } else if ((dataField.getExpressionGraph() != null) && dataField.getExpressionGraph().containsKey(
999 UifConstants.ComponentProperties.DEFAULT_VALUES)) {
1000 defaultValue = dataField.getExpressionGraph().get(UifConstants.ComponentProperties.DEFAULT_VALUES);
1001 } else if (dataField.getDefaultValues() != null) {
1002 defaultValue = dataField.getDefaultValues();
1003 }
1004
1005 ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
1006
1007 if ((defaultValue != null) && (defaultValue instanceof String) && expressionEvaluator.containsElPlaceholder(
1008 (String) defaultValue)) {
1009 Map<String, Object> context = new HashMap<String, Object>(view.getPreModelContext());
1010 context.putAll(dataField.getContext());
1011
1012 defaultValue = expressionEvaluator.replaceBindingPrefixes(view, object, (String) defaultValue);
1013 defaultValue = expressionEvaluator.evaluateExpressionTemplate(context, (String) defaultValue);
1014 }
1015
1016 return defaultValue;
1017 }
1018
1019
1020
1021
1022 @Override
1023 public void refreshReference(Object parentObject, String referenceObjectName) {
1024
1025 if (!(parentObject instanceof PersistableBusinessObjectBaseAdapter)) {
1026 KRADServiceLocator.getDataObjectService().wrap(parentObject).fetchRelationship(referenceObjectName);
1027 }
1028 else {
1029
1030 LegacyDataAdapter legacyDataAdapter = KRADServiceLocatorWeb.getLegacyDataAdapter();
1031 DataDictionaryService dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
1032
1033 if (legacyDataAdapter.hasReference(parentObject.getClass(), referenceObjectName) || legacyDataAdapter
1034 .hasCollection(parentObject.getClass(), referenceObjectName)) {
1035
1036 legacyDataAdapter.retrieveReferenceObject(parentObject, referenceObjectName);
1037 } else if (dataDictionaryService.hasRelationship(parentObject.getClass().getName(), referenceObjectName)) {
1038
1039 Object referenceObject = KradDataServiceLocator.getDataObjectService().wrap(parentObject).getPropertyValue(
1040 referenceObjectName);
1041 if (!(referenceObject instanceof PersistableBusinessObjectBaseAdapter)) {
1042 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1043 .getName() + ". Class not of type PersistableBusinessObject");
1044 return;
1045 }
1046
1047 referenceObject = legacyDataAdapter.retrieve(referenceObject);
1048 if (referenceObject == null) {
1049 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1050 .getName() + ".");
1051 return;
1052 }
1053
1054 try {
1055 KRADUtils.setObjectProperty(parentObject, referenceObjectName, referenceObject);
1056 } catch (Exception e) {
1057 LOG.error("Unable to refresh persistable business object: " + referenceObjectName + "\n" + e
1058 .getMessage());
1059 throw new RuntimeException(
1060 "Unable to refresh persistable business object: " + referenceObjectName + "\n" + e
1061 .getMessage());
1062 }
1063 } else {
1064 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1065 .getName() + ".");
1066 }
1067 }
1068 }
1069
1070
1071
1072
1073 @Override
1074 public void refreshReferences(String referencesToRefresh) {
1075 Object model = ViewLifecycle.getModel();
1076 for (String reference : StringUtils.split(referencesToRefresh, KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR)) {
1077 if (StringUtils.isBlank(reference)) {
1078 continue;
1079 }
1080
1081
1082
1083 if (PropertyAccessorUtils.isNestedOrIndexedProperty(reference)) {
1084 String parentPath = KRADUtils.getNestedAttributePrefix(reference);
1085 Object parentObject = ObjectPropertyUtils.getPropertyValue(model, parentPath);
1086 String referenceObjectName = KRADUtils.getNestedAttributePrimitive(reference);
1087
1088 if (parentObject == null) {
1089 LOG.warn("Unable to refresh references for " + referencesToRefresh +
1090 ". Object not found in model. Nothing refreshed.");
1091 continue;
1092 }
1093
1094 refreshReference(parentObject, referenceObjectName);
1095 } else {
1096 refreshReference(model, reference);
1097 }
1098 }
1099 }
1100
1101
1102
1103
1104 @Override
1105 public void retrieveEditModesAndActionFlags() {
1106 View view = ViewLifecycle.getView();
1107 UifFormBase model = (UifFormBase) ViewLifecycle.getModel();
1108 ViewPresentationController presentationController = view.getPresentationController();
1109 ViewAuthorizer authorizer = view.getAuthorizer();
1110
1111 RequestAuthorizationCache requestAuthorizationCache;
1112 try {
1113 requestAuthorizationCache = view.getRequestAuthorizationCacheClass().newInstance();
1114 } catch (Exception e) {
1115 throw new RuntimeException("Cannot create instance of request authorization cache class", e);
1116 }
1117
1118 presentationController.setRequestAuthorizationCache(requestAuthorizationCache);
1119 authorizer.setRequestAuthorizationCache(requestAuthorizationCache);
1120
1121 Set<String> actionFlags = presentationController.getActionFlags(view, model);
1122 Set<String> editModes = presentationController.getEditModes(view, model);
1123
1124
1125 if (GlobalVariables.getUserSession() != null) {
1126 Person user = GlobalVariables.getUserSession().getPerson();
1127
1128 actionFlags = authorizer.getActionFlags(view, model, user, actionFlags);
1129 editModes = authorizer.getEditModes(view, model, user, editModes);
1130 }
1131
1132 view.setActionFlags(new BooleanMap(actionFlags));
1133 view.setEditModes(new BooleanMap(editModes));
1134 }
1135
1136
1137
1138
1139 @Override
1140 public void setViewContext() {
1141 View view = ViewLifecycle.getView();
1142 view.pushAllToContext(view.getPreModelContext());
1143
1144
1145 for (Entry<String, String> variableExpression : view.getExpressionVariables().entrySet()) {
1146 String variableName = variableExpression.getKey();
1147 Object value = ViewLifecycle.getExpressionEvaluator().evaluateExpression(view.getContext(),
1148 variableExpression.getValue());
1149 view.pushObjectToContext(variableName, value);
1150 }
1151 }
1152
1153
1154
1155
1156 @Override
1157 public void setElementContext(LifecycleElement element, LifecycleElement parent) {
1158 Map<String, Object> context = new HashMap<String, Object>();
1159
1160 View view = ViewLifecycle.getView();
1161 Map<String, Object> viewContext = view.getContext();
1162 if (viewContext != null) {
1163 context.putAll(viewContext);
1164 }
1165
1166 context.put(UifConstants.ContextVariableNames.COMPONENT, element instanceof Component ? element : parent);
1167
1168 if (parent != null) {
1169 context.put(UifConstants.ContextVariableNames.PARENT, parent);
1170 }
1171
1172 if (element instanceof LayoutManager) {
1173 context.put(UifConstants.ContextVariableNames.MANAGER, element);
1174 }
1175
1176 element.pushAllToContext(context);
1177 }
1178
1179
1180
1181
1182
1183
1184 protected ConfigurationService getConfigurationService() {
1185 if (this.configurationService == null) {
1186 this.configurationService = CoreApiServiceLocator.getKualiConfigurationService();
1187 }
1188 return this.configurationService;
1189 }
1190
1191
1192
1193
1194
1195
1196 public void setConfigurationService(ConfigurationService configurationService) {
1197 this.configurationService = configurationService;
1198 }
1199
1200
1201
1202
1203
1204
1205 protected DataDictionaryService getDataDictionaryService() {
1206 if (this.dataDictionaryService == null) {
1207 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
1208 }
1209
1210 return this.dataDictionaryService;
1211 }
1212
1213
1214
1215
1216
1217
1218 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1219 this.dataDictionaryService = dataDictionaryService;
1220 }
1221
1222
1223
1224
1225
1226
1227 protected ViewDictionaryService getViewDictionaryService() {
1228 if (this.viewDictionaryService == null) {
1229 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
1230 }
1231 return this.viewDictionaryService;
1232 }
1233
1234
1235
1236
1237
1238
1239 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
1240 this.viewDictionaryService = viewDictionaryService;
1241 }
1242
1243
1244
1245
1246 @Override
1247 public ExpressionEvaluatorFactory getExpressionEvaluatorFactory() {
1248 if (expressionEvaluatorFactory == null) {
1249 expressionEvaluatorFactory = KRADServiceLocatorWeb.getExpressionEvaluatorFactory();
1250 }
1251
1252 return expressionEvaluatorFactory;
1253 }
1254
1255
1256
1257
1258
1259
1260 public void setExpressionEvaluatorFactory(ExpressionEvaluatorFactory expressionEvaluatorFactory) {
1261 this.expressionEvaluatorFactory = expressionEvaluatorFactory;
1262 }
1263
1264
1265
1266
1267
1268
1269 protected LegacyDataAdapter getLegacyDataAdapter() {
1270 if (legacyDataAdapter == null) {
1271 legacyDataAdapter = KRADServiceLocatorWeb.getLegacyDataAdapter();
1272 }
1273 return legacyDataAdapter;
1274 }
1275
1276 protected DataObjectService getDataObjectService() {
1277 if (dataObjectService == null) {
1278 dataObjectService = KRADServiceLocator.getDataObjectService();
1279 }
1280 return dataObjectService;
1281 }
1282
1283 protected void setDataObjectService(DataObjectService dataObjectService) {
1284 this.dataObjectService = dataObjectService;
1285 }
1286
1287
1288
1289
1290
1291
1292 public void setLegacyDataAdapter(LegacyDataAdapter legacyDataAdapter) {
1293 this.legacyDataAdapter = legacyDataAdapter;
1294 }
1295
1296
1297
1298
1299
1300
1301 protected void logAndThrowRuntime(String message) {
1302 LOG.error(message);
1303 throw new RuntimeException(message);
1304 }
1305
1306 }