1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kns.util;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.CoreApiServiceLocator;
21 import org.kuali.rice.core.api.encryption.EncryptionService;
22 import org.kuali.rice.core.api.uif.Control;
23 import org.kuali.rice.core.api.uif.DataType;
24 import org.kuali.rice.core.api.uif.RemotableAbstractControl;
25 import org.kuali.rice.core.api.uif.RemotableAbstractWidget;
26 import org.kuali.rice.core.api.uif.RemotableAttributeField;
27 import org.kuali.rice.core.api.uif.RemotableAttributeLookupSettings;
28 import org.kuali.rice.core.api.uif.RemotableCheckboxGroup;
29 import org.kuali.rice.core.api.uif.RemotableDatepicker;
30 import org.kuali.rice.core.api.uif.RemotableHiddenInput;
31 import org.kuali.rice.core.api.uif.RemotablePasswordInput;
32 import org.kuali.rice.core.api.uif.RemotableQuickFinder;
33 import org.kuali.rice.core.api.uif.RemotableRadioButtonGroup;
34 import org.kuali.rice.core.api.uif.RemotableSelect;
35 import org.kuali.rice.core.api.uif.RemotableTextExpand;
36 import org.kuali.rice.core.api.uif.RemotableTextInput;
37 import org.kuali.rice.core.api.uif.RemotableTextarea;
38 import org.kuali.rice.core.api.util.ClassLoaderUtils;
39 import org.kuali.rice.core.api.util.ConcreteKeyValue;
40 import org.kuali.rice.core.api.util.KeyValue;
41 import org.kuali.rice.core.web.format.FormatException;
42 import org.kuali.rice.core.web.format.Formatter;
43 import org.kuali.rice.kew.util.KEWConstants;
44 import org.kuali.rice.kim.api.identity.Person;
45 import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
46 import org.kuali.rice.kns.datadictionary.FieldDefinition;
47 import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
48 import org.kuali.rice.kns.datadictionary.control.ButtonControlDefinition;
49 import org.kuali.rice.kns.datadictionary.control.CurrencyControlDefinition;
50 import org.kuali.rice.kns.datadictionary.control.KualiUserControlDefinition;
51 import org.kuali.rice.kns.datadictionary.control.LinkControlDefinition;
52 import org.kuali.rice.kns.document.authorization.FieldRestriction;
53 import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
54 import org.kuali.rice.kns.inquiry.Inquirable;
55 import org.kuali.rice.kns.lookup.HtmlData;
56 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
57 import org.kuali.rice.kns.lookup.LookupUtils;
58 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
59 import org.kuali.rice.kns.service.KNSServiceLocator;
60 import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
61 import org.kuali.rice.kns.web.ui.Column;
62 import org.kuali.rice.kns.web.ui.Field;
63 import org.kuali.rice.kns.web.ui.PropertyRenderingConfigElement;
64 import org.kuali.rice.kns.web.ui.Row;
65 import org.kuali.rice.kns.web.ui.Section;
66 import org.kuali.rice.krad.bo.BusinessObject;
67 import org.kuali.rice.krad.bo.DataObjectRelationship;
68 import org.kuali.rice.krad.bo.KualiCode;
69 import org.kuali.rice.krad.bo.MutableInactivatable;
70 import org.kuali.rice.krad.bo.PersistableBusinessObject;
71 import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
72 import org.kuali.rice.krad.datadictionary.exception.UnknownBusinessClassAttributeException;
73 import org.kuali.rice.krad.datadictionary.mask.MaskFormatter;
74 import org.kuali.rice.krad.keyvalues.IndicatorValuesFinder;
75 import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
76 import org.kuali.rice.krad.keyvalues.PersistableBusinessObjectValuesFinder;
77 import org.kuali.rice.krad.service.BusinessObjectDictionaryService;
78 import org.kuali.rice.krad.service.DataDictionaryService;
79 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
80 import org.kuali.rice.krad.service.KualiModuleService;
81 import org.kuali.rice.krad.service.ModuleService;
82 import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
83 import org.kuali.rice.krad.util.GlobalVariables;
84 import org.kuali.rice.krad.util.KRADConstants;
85 import org.kuali.rice.krad.util.KRADPropertyConstants;
86 import org.kuali.rice.krad.util.MessageMap;
87 import org.kuali.rice.krad.util.ObjectUtils;
88 import org.kuali.rice.krad.valuefinder.ValueFinder;
89
90 import java.lang.reflect.InvocationTargetException;
91 import java.security.GeneralSecurityException;
92 import java.util.ArrayList;
93 import java.util.Collection;
94 import java.util.Collections;
95 import java.util.HashMap;
96 import java.util.Iterator;
97 import java.util.List;
98 import java.util.Map;
99
100
101
102
103
104 public final class FieldUtils {
105 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(FieldUtils.class);
106 private static DataDictionaryService dataDictionaryService = null;
107 private static BusinessObjectMetaDataService businessObjectMetaDataService = null;
108 private static BusinessObjectDictionaryService businessObjectDictionaryService = null;
109 private static KualiModuleService kualiModuleService = null;
110
111 private FieldUtils() {
112 throw new UnsupportedOperationException("do not call");
113 }
114
115 public static void setInquiryURL(Field field, BusinessObject bo, String propertyName) {
116 HtmlData inquiryHref = new AnchorHtmlData(KRADConstants.EMPTY_STRING, KRADConstants.EMPTY_STRING);
117
118 Boolean b = getBusinessObjectDictionaryService().noInquiryFieldInquiry(bo.getClass(), propertyName);
119 if (b == null || !b.booleanValue()) {
120 Class<Inquirable> inquirableClass = getBusinessObjectDictionaryService().getInquirableClass(bo.getClass());
121 Boolean b2 = getBusinessObjectDictionaryService().forceLookupResultFieldInquiry(bo.getClass(), propertyName);
122 Inquirable inq = null;
123 try {
124 if ( inquirableClass != null ) {
125 inq = inquirableClass.newInstance();
126 } else {
127 inq = KNSServiceLocator.getKualiInquirable();
128 if ( LOG.isDebugEnabled() ) {
129 LOG.debug( "Default Inquirable Class: " + inq.getClass() );
130 }
131 }
132
133 inquiryHref = inq.getInquiryUrl(bo, propertyName, null == b2 ? false : b2.booleanValue() );
134
135 } catch ( Exception ex ) {
136 LOG.error("unable to create inquirable to get inquiry URL", ex );
137 }
138 }
139
140 field.setInquiryURL(inquiryHref);
141 }
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public static void setFieldControl(Class businessObjectClass, String attributeName, boolean convertForLookup,
156 Field field) {
157 ControlDefinition control = getDataDictionaryService().getAttributeControlDefinition(businessObjectClass,
158 attributeName);
159 String fieldType = Field.TEXT;
160
161 if (control != null) {
162 if (control.isSelect()) {
163 if (control.getScript() != null && control.getScript().length() > 0) {
164 fieldType = Field.DROPDOWN_SCRIPT;
165 field.setScript(control.getScript());
166 } else {
167 fieldType = Field.DROPDOWN;
168 }
169 }
170
171 if (control.isMultiselect()) {
172 fieldType = Field.MULTISELECT;
173 }
174
175 if (control.isCheckbox()) {
176 fieldType = Field.CHECKBOX;
177 }
178
179 if (control.isRadio()) {
180 fieldType = Field.RADIO;
181 }
182
183 if (control.isHidden()) {
184 fieldType = Field.HIDDEN;
185 }
186
187 if (control.isKualiUser()) {
188 fieldType = Field.KUALIUSER;
189 KualiUserControlDefinition kualiUserControl = (KualiUserControlDefinition) control;
190 field.setUniversalIdAttributeName(kualiUserControl.getUniversalIdAttributeName());
191 field.setUserIdAttributeName(kualiUserControl.getUserIdAttributeName());
192 field.setPersonNameAttributeName(kualiUserControl.getPersonNameAttributeName());
193 }
194
195 if (control.isWorkflowWorkgroup()) {
196 fieldType = Field.WORKFLOW_WORKGROUP;
197 }
198
199 if (control.isFile()) {
200 fieldType = Field.FILE;
201 }
202
203 if (control.isTextarea() && !convertForLookup) {
204 fieldType = Field.TEXT_AREA;
205 }
206
207 if (control.isLookupHidden()) {
208 fieldType = Field.LOOKUP_HIDDEN;
209 }
210
211 if (control.isLookupReadonly()) {
212 fieldType = Field.LOOKUP_READONLY;
213 }
214
215 if (control.isCurrency()) {
216 fieldType = Field.CURRENCY;
217 }
218
219 if (control.isButton()) {
220 fieldType = Field.BUTTON;
221 }
222
223 if (control.isLink()) {
224 fieldType = Field.LINK;
225 }
226
227 if (Field.CURRENCY.equals(fieldType) && control instanceof CurrencyControlDefinition) {
228 CurrencyControlDefinition currencyControl = (CurrencyControlDefinition) control;
229 field.setStyleClass("amount");
230 field.setSize(currencyControl.getSize());
231 field.setFormattedMaxLength(currencyControl.getFormattedMaxLength());
232 }
233
234
235 if (Field.TEXT.equals(fieldType)) {
236 Integer size = control.getSize();
237 if (size != null) {
238 field.setSize(size.intValue());
239 } else {
240 field.setSize(30);
241 }
242 field.setDatePicker(control.isDatePicker());
243 field.setRanged(control.isRanged());
244 }
245
246 if (Field.WORKFLOW_WORKGROUP.equals(fieldType)) {
247 Integer size = control.getSize();
248 if (size != null) {
249 field.setSize(size.intValue());
250 } else {
251 field.setSize(30);
252 }
253 }
254
255
256 if (Field.TEXT_AREA.equals(fieldType)) {
257 Integer rows = control.getRows();
258 if (rows != null) {
259 field.setRows(rows.intValue());
260 } else {
261 field.setRows(3);
262 }
263
264 Integer cols = control.getCols();
265 if (cols != null) {
266 field.setCols(cols.intValue());
267 } else {
268 field.setCols(40);
269 }
270 field.setExpandedTextArea(control.isExpandedTextArea());
271 }
272
273 if (Field.MULTISELECT.equals(fieldType)) {
274 Integer size = control.getSize();
275 if (size != null) {
276 field.setSize(size.intValue());
277 }
278 }
279
280
281 if (Field.DROPDOWN.equals(fieldType) || Field.RADIO.equals(fieldType)
282 || Field.DROPDOWN_SCRIPT.equals(fieldType)
283 || Field.MULTISELECT.equals(fieldType)) {
284 String keyFinderClassName = control.getValuesFinderClass();
285
286 if (StringUtils.isNotBlank(keyFinderClassName)) {
287 try {
288 Class keyFinderClass = ClassLoaderUtils.getClass(keyFinderClassName);
289 KeyValuesFinder finder = (KeyValuesFinder) keyFinderClass.newInstance();
290
291 if (finder != null) {
292 if (finder instanceof PersistableBusinessObjectValuesFinder) {
293 ((PersistableBusinessObjectValuesFinder) finder)
294 .setBusinessObjectClass(ClassLoaderUtils.getClass(control
295 .getBusinessObjectClass()));
296 ((PersistableBusinessObjectValuesFinder) finder).setKeyAttributeName(control
297 .getKeyAttribute());
298 ((PersistableBusinessObjectValuesFinder) finder).setLabelAttributeName(control
299 .getLabelAttribute());
300 if (control.getIncludeBlankRow() != null) {
301 ((PersistableBusinessObjectValuesFinder) finder).setIncludeBlankRow(control
302 .getIncludeBlankRow());
303 }
304 ((PersistableBusinessObjectValuesFinder) finder).setIncludeKeyInDescription(control
305 .getIncludeKeyInLabel());
306 }
307 field.setFieldValidValues(finder.getKeyValues());
308 field.setFieldInactiveValidValues(finder.getKeyValues(false));
309 }
310 } catch (InstantiationException e) {
311 LOG.error("Unable to get new instance of finder class: " + keyFinderClassName);
312 throw new RuntimeException("Unable to get new instance of finder class: " + keyFinderClassName);
313 } catch (IllegalAccessException e) {
314 LOG.error("Unable to get new instance of finder class: " + keyFinderClassName);
315 throw new RuntimeException("Unable to get new instance of finder class: " + keyFinderClassName);
316 }
317 }
318 }
319
320 if (Field.CHECKBOX.equals(fieldType) && convertForLookup) {
321 fieldType = Field.RADIO;
322 field.setFieldValidValues(IndicatorValuesFinder.INSTANCE.getKeyValues());
323 }
324
325
326 if (Field.BUTTON.equals(fieldType)) {
327 ButtonControlDefinition buttonControl = (ButtonControlDefinition) control;
328 field.setImageSrc(buttonControl.getImageSrc());
329 field.setStyleClass(buttonControl.getStyleClass());
330 }
331
332
333 if (Field.LINK.equals(fieldType)) {
334 LinkControlDefinition linkControl = (LinkControlDefinition) control;
335 field.setStyleClass(linkControl.getStyleClass());
336 field.setTarget(linkControl.getTarget());
337 field.setHrefText(linkControl.getHrefText());
338 }
339
340 }
341
342 field.setFieldType(fieldType);
343 }
344
345
346
347
348
349
350
351
352 public static Field getPropertyField(Class businessObjectClass, String attributeName, boolean convertForLookup) {
353 Field field = new Field();
354 field.setPropertyName(attributeName);
355 field.setFieldLabel(getDataDictionaryService().getAttributeLabel(businessObjectClass, attributeName));
356
357 setFieldControl(businessObjectClass, attributeName, convertForLookup, field);
358
359 Boolean fieldRequired = getBusinessObjectDictionaryService().getLookupAttributeRequired(businessObjectClass, attributeName);
360 if (fieldRequired != null) {
361 field.setFieldRequired(fieldRequired.booleanValue());
362 }
363
364 Integer maxLength = getDataDictionaryService().getAttributeMaxLength(businessObjectClass, attributeName);
365 if (maxLength != null) {
366 field.setMaxLength(maxLength.intValue());
367 }
368
369 Boolean upperCase = null;
370 try {
371 upperCase = getDataDictionaryService().getAttributeForceUppercase(businessObjectClass, attributeName);
372 }
373 catch (UnknownBusinessClassAttributeException t) {
374
375 LOG.warn( "UnknownBusinessClassAttributeException in fieldUtils.getPropertyField() : " + t.getMessage() );
376 }
377 if (upperCase != null) {
378 field.setUpperCase(upperCase.booleanValue());
379 }
380
381 if (!businessObjectClass.isInterface()) {
382 try {
383 field.setFormatter(
384 ObjectUtils.getFormatterWithDataDictionary(businessObjectClass.newInstance(), attributeName));
385 } catch (InstantiationException e) {
386 LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
387
388 } catch (IllegalAccessException e) {
389 LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
390
391 }
392 }
393
394
395 field.setBusinessObjectClassName(businessObjectClass.getName());
396 field.setFieldHelpName(attributeName);
397 field.setFieldHelpSummary(getDataDictionaryService().getAttributeSummary(businessObjectClass, attributeName));
398
399 return field;
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414 public static void setAdditionalDisplayPropertyForCodes(Class businessObjectClass, String attributeName, PropertyRenderingConfigElement field) {
415 try {
416 DataObjectRelationship relationship = getBusinessObjectMetaDataService().getBusinessObjectRelationship(
417 (BusinessObject) businessObjectClass.newInstance(), attributeName);
418
419 if (relationship != null && attributeName.startsWith(relationship.getParentAttributeName())
420 && KualiCode.class.isAssignableFrom(relationship.getRelatedClass())) {
421 field.setAdditionalDisplayPropertyName(relationship.getParentAttributeName() + "."
422 + KRADPropertyConstants.NAME);
423 }
424 } catch (Exception e) {
425 throw new RuntimeException("Cannot get new instance of class to check for KualiCode references: "
426 + e.getMessage());
427 }
428 }
429
430
431
432
433
434
435
436
437 public static List wrapFields(List fields) {
438 return wrapFields(fields, KRADConstants.DEFAULT_NUM_OF_COLUMNS);
439 }
440
441
442
443
444
445
446
447
448 public static List<Row> wrapFields(List<Field> fields, int numberOfColumns) {
449
450 List<Row> rows = new ArrayList();
451 List<Field> fieldOnlyList = new ArrayList();
452
453 List<Field> visableFields = getVisibleFields(fields);
454 List<Field> nonVisableFields = getNonVisibleFields(fields);
455
456 int fieldsPosition = 0;
457 for (Field element : visableFields) {
458 if (Field.SUB_SECTION_SEPARATOR.equals(element.getFieldType()) || Field.CONTAINER.equals(element.getFieldType())) {
459 fieldsPosition = createBlankSpace(fieldOnlyList, rows, numberOfColumns, fieldsPosition);
460 List fieldList = new ArrayList();
461 fieldList.add(element);
462 rows.add(new Row(fieldList));
463 }
464 else {
465 if (fieldsPosition < numberOfColumns) {
466 fieldOnlyList.add(element);
467 fieldsPosition++;
468 }
469 else {
470 rows.add(new Row(new ArrayList(fieldOnlyList)));
471 fieldOnlyList.clear();
472 fieldOnlyList.add(element);
473 fieldsPosition = 1;
474 }
475 }
476 }
477 createBlankSpace(fieldOnlyList, rows, numberOfColumns, fieldsPosition);
478
479
480 if(nonVisableFields != null && !nonVisableFields.isEmpty()){
481 Row nonVisRow = new Row();
482 nonVisRow.setFields(nonVisableFields);
483 rows.add(nonVisRow);
484 }
485
486
487 return rows;
488 }
489
490 private static List<Field> getVisibleFields(List<Field> fields){
491 List<Field> rList = new ArrayList<Field>();
492
493 for(Field f: fields){
494 if(!Field.HIDDEN.equals(f.getFieldType()) && !Field.BLANK_SPACE.equals(f.getFieldType())){
495 rList.add(f);
496 }
497 }
498
499 return rList;
500 }
501
502 private static List<Field> getNonVisibleFields(List<Field> fields){
503 List<Field> rList = new ArrayList<Field>();
504
505 for(Field f: fields){
506 if(Field.HIDDEN.equals(f.getFieldType()) || Field.BLANK_SPACE.equals(f.getFieldType())){
507 rList.add(f);
508 }
509 }
510
511 return rList;
512 }
513
514
515
516
517
518
519
520
521
522 private static int createBlankSpace(List<Field> fieldOnlyList, List<Row> rows, int numberOfColumns, int fieldsPosition) {
523 int fieldOnlySize = fieldOnlyList.size();
524 if (fieldOnlySize > 0) {
525 for (int i = 0; i < (numberOfColumns - fieldOnlySize); i++) {
526 Field empty = new Field();
527 empty.setFieldType(Field.BLANK_SPACE);
528
529 empty.setPropertyName(Field.BLANK_SPACE);
530 fieldOnlyList.add(empty);
531 }
532 rows.add(new Row(new ArrayList(fieldOnlyList)));
533 fieldOnlyList.clear();
534 fieldsPosition = 0;
535 }
536 return fieldsPosition;
537 }
538
539
540
541
542
543
544
545
546
547 public static Field constructContainerField(String name, String label, List fields) {
548 return constructContainerField(name, label, fields, KRADConstants.DEFAULT_NUM_OF_COLUMNS);
549 }
550
551
552
553
554
555
556
557
558
559
560 public static Field constructContainerField(String name, String label, List fields, int numberOfColumns) {
561 Field containerField = new Field();
562 containerField.setPropertyName(name);
563 containerField.setFieldLabel(label);
564 containerField.setFieldType(Field.CONTAINER);
565 containerField.setNumberOfColumnsForCollection(numberOfColumns);
566
567 List rows = wrapFields(fields, numberOfColumns);
568 containerField.setContainerRows(rows);
569
570 return containerField;
571 }
572
573
574
575
576
577
578
579
580
581 public static List<Field> populateFieldsFromBusinessObject(List<Field> fields, BusinessObject bo) {
582 List<Field> populatedFields = new ArrayList<Field>();
583
584 if (bo instanceof PersistableBusinessObject) {
585 ((PersistableBusinessObject) bo).refreshNonUpdateableReferences();
586 }
587
588 for (Iterator<Field> iter = fields.iterator(); iter.hasNext();) {
589 Field element = iter.next();
590 if (element.containsBOData()) {
591 String propertyName = element.getPropertyName();
592
593
594
595
596 if (isPropertyNested(propertyName) && !isObjectTreeNonNullAllTheWayDown(bo, propertyName) && ((!element.getFieldType().equals(Field.IMAGE_SUBMIT)) && !(element.getFieldType().equals(Field.CONTAINER)) && (!element.getFieldType().equals(Field.QUICKFINDER)))) {
597 element.setPropertyValue(null);
598 }
599 else if (PropertyUtils.isReadable(bo, propertyName)) {
600 populateReadableField(element, bo);
601 }
602
603 if (StringUtils.isNotBlank(element.getAlternateDisplayPropertyName())) {
604 String alternatePropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(bo, element
605 .getAlternateDisplayPropertyName());
606 element.setAlternateDisplayPropertyValue(alternatePropertyValue);
607 }
608
609 if (StringUtils.isNotBlank(element.getAdditionalDisplayPropertyName())) {
610 String additionalPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(bo, element
611 .getAdditionalDisplayPropertyName());
612 element.setAdditionalDisplayPropertyValue(additionalPropertyValue);
613 }
614 }
615 populatedFields.add(element);
616 }
617
618 return populatedFields;
619 }
620
621 public static void populateReadableField(Field field, BusinessObject businessObject){
622 Object obj = ObjectUtils.getNestedValue(businessObject, field.getPropertyName());
623 if (obj != null) {
624 String formattedValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(businessObject, field.getPropertyName());
625 field.setPropertyValue(formattedValue);
626
627
628 if ( field.getFieldType().equals(Field.KUALIUSER) ) {
629
630 try {
631 if ( StringUtils.isNotBlank(field.getUniversalIdAttributeName()) ) {
632 Object principalId = ObjectUtils.getNestedValue(businessObject, field.getUniversalIdAttributeName());
633 if ( principalId != null ) {
634 field.setUniversalIdValue(principalId.toString());
635 }
636 }
637 if ( StringUtils.isNotBlank(field.getPersonNameAttributeName()) ) {
638 Object personName = ObjectUtils.getNestedValue(businessObject, field.getPersonNameAttributeName());
639 if ( personName != null ) {
640 field.setPersonNameValue( personName.toString() );
641 }
642 }
643 } catch ( Exception ex ) {
644 LOG.warn( "Unable to get principal ID or person name property in FieldBridge.", ex );
645 }
646 }
647 }
648
649 populateSecureField(field, obj);
650 }
651
652 public static void populateSecureField(Field field, Object fieldValue){
653
654
655 if (field.isSecure()) {
656 try {
657 if (fieldValue != null && fieldValue.toString().endsWith(EncryptionService.HASH_POST_PREFIX)) {
658 field.setEncryptedValue(fieldValue.toString());
659 }
660 else {
661 field.setEncryptedValue(CoreApiServiceLocator.getEncryptionService().encrypt(fieldValue) + EncryptionService.ENCRYPTION_POST_PREFIX);
662 }
663 }
664 catch (GeneralSecurityException e) {
665 throw new RuntimeException("Unable to encrypt secure field " + e.getMessage());
666 }
667
668 }
669 }
670
671
672
673
674
675
676
677 static private boolean isPropertyNested(String propertyName) {
678 return -1 != propertyName.indexOf('.');
679 }
680
681
682
683
684
685
686
687
688
689 static private boolean isObjectTreeNonNullAllTheWayDown(BusinessObject bo, String propertyName) {
690 String[] propertyParts = propertyName.split("\\.");
691
692 StringBuffer property = new StringBuffer();
693 for (int i = 0; i < propertyParts.length - 1; i++) {
694
695 property.append((0 == property.length()) ? "" : ".").append(propertyParts[i]);
696 try {
697 if (null == PropertyUtils.getNestedProperty(bo, property.toString())) {
698 return false;
699 }
700 }
701 catch (Throwable t) {
702 LOG.debug("Either getter or setter not specified for property \"" + property.toString() + "\"", t);
703 return false;
704 }
705 }
706
707 return true;
708
709 }
710
711
712
713
714
715
716 private static boolean containsIntermediateNull(Object bo, String propertyName) {
717 boolean containsNull = false;
718
719 if (StringUtils.contains(propertyName, ".")) {
720 String prefix = StringUtils.substringBefore(propertyName, ".");
721 Object propertyValue = ObjectUtils.getPropertyValue(bo, prefix);
722
723 if (propertyValue == null) {
724 containsNull = true;
725 }
726 else {
727 String suffix = StringUtils.substringAfter(propertyName, ".");
728 containsNull = containsIntermediateNull(propertyValue, suffix);
729 }
730 }
731
732 return containsNull;
733 }
734
735
736
737
738
739
740
741
742
743 public static Map populateBusinessObjectFromMap(BusinessObject bo, Map fieldValues) {
744 return populateBusinessObjectFromMap(bo, fieldValues, "");
745 }
746
747
748
749
750
751
752
753
754
755
756 public static Map populateBusinessObjectFromMap(BusinessObject bo, Map<String, ?> fieldValues, String propertyNamePrefix) {
757 Map cachedValues = new HashMap();
758 MessageMap errorMap = GlobalVariables.getMessageMap();
759
760 try {
761 for (Iterator<String> iter = fieldValues.keySet().iterator(); iter.hasNext();) {
762 String propertyName = iter.next();
763
764 if (propertyName.endsWith(KRADConstants.CHECKBOX_PRESENT_ON_FORM_ANNOTATION)) {
765
766
767 if (StringUtils.isNotBlank((String) fieldValues.get(propertyName))) {
768 String checkboxName = StringUtils.removeEnd(propertyName, KRADConstants.CHECKBOX_PRESENT_ON_FORM_ANNOTATION);
769 String checkboxValue = (String) fieldValues.get(checkboxName);
770 if (checkboxValue == null) {
771
772 if (PropertyUtils.isWriteable(bo, checkboxName)) {
773 Class type = ObjectUtils.easyGetPropertyType(bo, checkboxName);
774 if (type == Boolean.TYPE || type == Boolean.class) {
775
776 ObjectUtils.setObjectProperty(bo, checkboxName, type, "false");
777 }
778 }
779 }
780 }
781
782
783 }
784 else if (PropertyUtils.isWriteable(bo, propertyName) && fieldValues.get(propertyName) != null ) {
785
786 Class type = ObjectUtils.easyGetPropertyType(bo, propertyName);
787 try {
788 Object fieldValue = fieldValues.get(propertyName);
789 ObjectUtils.setObjectProperty(bo, propertyName, type, fieldValue);
790 }
791 catch (FormatException e) {
792 cachedValues.put(propertyNamePrefix + propertyName, fieldValues.get(propertyName));
793 errorMap.putError(propertyNamePrefix + propertyName, e.getErrorKey(), e.getErrorArgs());
794 }
795 }
796 }
797 }
798 catch (IllegalAccessException e) {
799 LOG.error("unable to populate business object" + e.getMessage());
800 throw new RuntimeException(e.getMessage(), e);
801 }
802 catch (InvocationTargetException e) {
803 LOG.error("unable to populate business object" + e.getMessage());
804 throw new RuntimeException(e.getMessage(), e);
805 }
806 catch (NoSuchMethodException e) {
807 LOG.error("unable to populate business object" + e.getMessage());
808 throw new RuntimeException(e.getMessage(), e);
809 }
810
811 return cachedValues;
812 }
813
814
815
816
817
818
819
820
821
822
823
824 public static Field fixFieldForForm(Field field, List keyFieldNames, String namePrefix, String maintenanceAction, boolean readOnly, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
825 String propertyName = field.getPropertyName();
826
827 if (field.containsBOData()) {
828
829
830 if (!propertyName.startsWith(KRADConstants.DISPATCH_REQUEST_PARAMETER)) {
831
832 if (field.getPropertyPrefix() == null || field.getPropertyPrefix().equals("")) {
833 field.setPropertyName(namePrefix + propertyName);
834 }
835 else {
836 field.setPropertyName(field.getPropertyPrefix() + "." + propertyName);
837 }
838 }
839
840 if (readOnly) {
841 field.setReadOnly(true);
842 }
843
844
845 if ( KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction) ) {
846 if (keyFieldNames.contains(propertyName) ) {
847 field.setReadOnly(true);
848 field.setKeyField(true);
849 } else if ( StringUtils.isNotBlank( field.getUniversalIdAttributeName() )
850 && keyFieldNames.contains(field.getUniversalIdAttributeName() ) ) {
851
852
853 field.setReadOnly(true);
854 field.setKeyField(true);
855 }
856 }
857
858
859 applyAuthorization(field, maintenanceAction, auths, documentStatus, documentInitiatorPrincipalId);
860
861
862 if (StringUtils.isNotBlank(field.getFieldConversions())) {
863 String fieldConversions = field.getFieldConversions();
864 String newFieldConversions = KRADConstants.EMPTY_STRING;
865 String[] conversions = StringUtils.split(fieldConversions, KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
866
867 for (int l = 0; l < conversions.length; l++) {
868 String conversion = conversions[l];
869
870 String[] conversionPair = StringUtils.split(conversion, KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2);
871 String conversionFrom = conversionPair[0];
872 String conversionTo = conversionPair[1];
873 conversionTo = KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + conversionTo;
874 newFieldConversions += (conversionFrom + KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR + conversionTo);
875
876 if (l < conversions.length) {
877 newFieldConversions += KRADConstants.FIELD_CONVERSIONS_SEPARATOR;
878 }
879 }
880
881 field.setFieldConversions(newFieldConversions);
882 }
883
884
885 if (StringUtils.isNotBlank(field.getInquiryParameters())) {
886 String inquiryParameters = field.getInquiryParameters();
887 StringBuilder newInquiryParameters = new StringBuilder();
888 String[] parameters = StringUtils.split(inquiryParameters, KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
889
890 for (int l = 0; l < parameters.length; l++) {
891 String parameter = parameters[l];
892
893 String[] parameterPair = StringUtils.split(parameter, KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2);
894 String conversionFrom = parameterPair[0];
895 String conversionTo = parameterPair[1];
896
897
898 newInquiryParameters.append(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE).append(conversionFrom);
899
900 newInquiryParameters.append(KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR).append(conversionTo);
901
902 if (l < parameters.length - 1) {
903 newInquiryParameters.append(KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
904 }
905 }
906
907 field.setInquiryParameters(newInquiryParameters.toString());
908 }
909
910 if (Field.KUALIUSER.equals(field.getFieldType())) {
911
912 int suffixIndex = field.getPropertyName().indexOf( field.getUserIdAttributeName() );
913 if ( suffixIndex != -1 ) {
914 field.setPersonNameAttributeName( field.getPropertyName().substring( 0, suffixIndex ) + field.getPersonNameAttributeName() );
915 field.setUniversalIdAttributeName( field.getPropertyName().substring( 0, suffixIndex ) + field.getUniversalIdAttributeName() );
916 } else {
917 field.setPersonNameAttributeName(namePrefix + field.getPersonNameAttributeName());
918 field.setUniversalIdAttributeName(namePrefix + field.getUniversalIdAttributeName());
919 }
920
921
922 }
923
924
925 if (StringUtils.isNotBlank(field.getLookupParameters())) {
926 String lookupParameters = field.getLookupParameters();
927 String newLookupParameters = KRADConstants.EMPTY_STRING;
928 String[] conversions = StringUtils.split(lookupParameters, KRADConstants.FIELD_CONVERSIONS_SEPARATOR);
929
930 for (int m = 0; m < conversions.length; m++) {
931 String conversion = conversions[m];
932
933 String[] conversionPair = StringUtils.split(conversion, KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR, 2);
934 String conversionFrom = conversionPair[0];
935 String conversionTo = conversionPair[1];
936 conversionFrom = KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + conversionFrom;
937 newLookupParameters += (conversionFrom + KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR + conversionTo);
938
939 if (m < conversions.length) {
940 newLookupParameters += KRADConstants.FIELD_CONVERSIONS_SEPARATOR;
941 }
942 }
943
944 field.setLookupParameters(newLookupParameters);
945 }
946
947
948 if (Field.CONTAINER.equals(field.getFieldType())) {
949 List containerRows = field.getContainerRows();
950 List fixedRows = new ArrayList();
951
952 for (Iterator iter = containerRows.iterator(); iter.hasNext();) {
953 Row containerRow = (Row) iter.next();
954 List containerFields = containerRow.getFields();
955 List fixedFields = new ArrayList();
956
957 for (Iterator iterator = containerFields.iterator(); iterator.hasNext();) {
958 Field containerField = (Field) iterator.next();
959 containerField = fixFieldForForm(containerField, keyFieldNames, namePrefix, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
960 fixedFields.add(containerField);
961 }
962
963 fixedRows.add(new Row(fixedFields));
964 }
965
966 field.setContainerRows(fixedRows);
967 }
968 }
969 return field;
970 }
971
972 public static void applyAuthorization(Field field, String maintenanceAction, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
973 String fieldName = "";
974 FieldRestriction fieldAuth = null;
975 Person user = GlobalVariables.getUserSession().getPerson();
976
977 if (field.getPropertyName().startsWith(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE)) {
978
979 fieldName = field.getPropertyName().substring(KRADConstants.MAINTENANCE_NEW_MAINTAINABLE.length());
980
981
982 if (auths.hasRestriction(fieldName)) {
983 fieldAuth = auths.getFieldRestriction(fieldName);
984 if(KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction) || KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)){
985 if((KEWConstants.ROUTE_HEADER_SAVED_CD.equals(documentStatus) || KEWConstants.ROUTE_HEADER_INITIATED_CD.equals(documentStatus))
986 && user.getPrincipalId().equals(documentInitiatorPrincipalId)){
987
988
989 }else{
990 if(fieldAuth.isPartiallyMasked()){
991 field.setSecure(true);
992 fieldAuth.setShouldBeEncrypted(true);
993 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
994 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
995 field.setDisplayMaskValue(displayMaskValue);
996 populateSecureField(field, field.getPropertyValue());
997 }
998 else if(fieldAuth.isMasked()){
999 field.setSecure(true);
1000 fieldAuth.setShouldBeEncrypted(true);
1001 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
1002 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
1003 field.setDisplayMaskValue(displayMaskValue);
1004 populateSecureField(field, field.getPropertyValue());
1005 }
1006 }
1007 }
1008
1009 if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction) || KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equals(maintenanceAction)) {
1010
1011 if(fieldAuth.isPartiallyMasked()){
1012 field.setSecure(true);
1013 fieldAuth.setShouldBeEncrypted(true);
1014 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
1015 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
1016 field.setDisplayMaskValue(displayMaskValue);
1017 populateSecureField(field, field.getPropertyValue());
1018 }
1019 else if(fieldAuth.isMasked()){
1020 field.setSecure(true);
1021 fieldAuth.setShouldBeEncrypted(true);
1022 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
1023 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
1024 field.setDisplayMaskValue(displayMaskValue);
1025 populateSecureField(field, field.getPropertyValue());
1026 }
1027 }
1028
1029 if (Field.isInputField(field.getFieldType()) || field.getFieldType().equalsIgnoreCase(Field.CHECKBOX)) {
1030
1031
1032 if (fieldAuth.isReadOnly()) {
1033 if (!field.isReadOnly() && !fieldAuth.isMasked() && !fieldAuth.isPartiallyMasked()) {
1034 field.setReadOnly(true);
1035 }
1036 }
1037 else if (fieldAuth.isHidden()) {
1038 if (field.getFieldType() != Field.HIDDEN) {
1039 field.setFieldType(Field.HIDDEN);
1040 }
1041 }
1042 }
1043
1044 if(Field.BUTTON.equalsIgnoreCase(field.getFieldType()) && fieldAuth.isHidden()){
1045 field.setFieldType(Field.HIDDEN);
1046 }
1047
1048
1049
1050 if (field.isReadOnly() && fieldAuth.isHidden()) {
1051 field.setFieldType(Field.HIDDEN);
1052 }
1053
1054 }
1055
1056
1057 }
1058 else if (field.getPropertyName().startsWith(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE)) {
1059
1060 fieldName = field.getPropertyName().substring(KRADConstants.MAINTENANCE_OLD_MAINTAINABLE.length());
1061
1062 if (auths.hasRestriction(fieldName)) {
1063 fieldAuth = auths.getFieldRestriction(fieldName);
1064 if(fieldAuth.isPartiallyMasked()){
1065 field.setSecure(true);
1066 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
1067 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
1068 field.setDisplayMaskValue(displayMaskValue);
1069 field.setPropertyValue(displayMaskValue);
1070 populateSecureField(field, field.getPropertyValue());
1071
1072 }
1073
1074 if(fieldAuth.isMasked()){
1075 field.setSecure(true);
1076 MaskFormatter maskFormatter = fieldAuth.getMaskFormatter();
1077 String displayMaskValue = maskFormatter.maskValue(field.getPropertyValue());
1078 field.setDisplayMaskValue(displayMaskValue);
1079 field.setPropertyValue(displayMaskValue);
1080 populateSecureField(field, field.getPropertyValue());
1081 }
1082
1083 if (fieldAuth.isHidden()) {
1084 field.setFieldType(Field.HIDDEN);
1085 }
1086 }
1087 }
1088 }
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100 public static List meshSections(List oldSections, List newSections, List keyFieldNames, String maintenanceAction, boolean readOnly, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
1101 List meshedSections = new ArrayList();
1102
1103 for (int i = 0; i < newSections.size(); i++) {
1104 Section maintSection = (Section) newSections.get(i);
1105 List sectionRows = maintSection.getRows();
1106 Section oldMaintSection = (Section) oldSections.get(i);
1107 List oldSectionRows = oldMaintSection.getRows();
1108 List<Row> meshedRows = new ArrayList();
1109 meshedRows = meshRows(oldSectionRows, sectionRows, keyFieldNames, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
1110 maintSection.setRows(meshedRows);
1111 if (StringUtils.isBlank(maintSection.getErrorKey())) {
1112 maintSection.setErrorKey(MaintenanceUtils.generateErrorKeyForSection(maintSection));
1113 }
1114 meshedSections.add(maintSection);
1115 }
1116
1117 return meshedSections;
1118 }
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130 public static List meshRows(List oldRows, List newRows, List keyFieldNames, String maintenanceAction, boolean readOnly, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
1131 List<Row> meshedRows = new ArrayList<Row>();
1132
1133 for (int j = 0; j < newRows.size(); j++) {
1134 Row sectionRow = (Row) newRows.get(j);
1135 List rowFields = sectionRow.getFields();
1136 Row oldSectionRow = null;
1137 List oldRowFields = new ArrayList();
1138
1139 if (null != oldRows && oldRows.size() > j) {
1140 oldSectionRow = (Row) oldRows.get(j);
1141 oldRowFields = oldSectionRow.getFields();
1142 }
1143
1144 List meshedFields = meshFields(oldRowFields, rowFields, keyFieldNames, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
1145 if (meshedFields.size() > 0) {
1146 Row meshedRow = new Row(meshedFields);
1147 if (sectionRow.isHidden()) {
1148 meshedRow.setHidden(true);
1149 }
1150
1151 meshedRows.add(meshedRow);
1152 }
1153 }
1154
1155 return meshedRows;
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169 public static List meshFields(List oldFields, List newFields, List keyFieldNames, String maintenanceAction, boolean readOnly, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
1170 List meshedFields = new ArrayList();
1171
1172 List newFieldsToMerge = new ArrayList();
1173 List oldFieldsToMerge = new ArrayList();
1174
1175 for (int k = 0; k < newFields.size(); k++) {
1176 Field newMaintField = (Field) newFields.get(k);
1177 String propertyName = newMaintField.getPropertyName();
1178
1179 if (Field.IMAGE_SUBMIT.equals(newMaintField.getFieldType())) {
1180 meshedFields.add(newMaintField);
1181 }
1182 else if (Field.CONTAINER.equals(newMaintField.getFieldType())) {
1183 if (oldFields.size() > k) {
1184 Field oldMaintField = (Field) oldFields.get(k);
1185 newMaintField = meshContainerFields(oldMaintField, newMaintField, keyFieldNames, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
1186 }
1187 else {
1188 newMaintField = meshContainerFields(newMaintField, newMaintField, keyFieldNames, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
1189 }
1190 meshedFields.add(newMaintField);
1191 }
1192 else {
1193 newMaintField = FieldUtils.fixFieldForForm(newMaintField, keyFieldNames, KRADConstants.MAINTENANCE_NEW_MAINTAINABLE, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId);
1194
1195 if (KRADConstants.MAINTENANCE_EDIT_ACTION.equals(maintenanceAction) || KRADConstants.MAINTENANCE_COPY_ACTION.equals(maintenanceAction)) {
1196 Field oldMaintField = (Field) oldFields.get(k);
1197
1198
1199
1200 if (!StringUtils.equalsIgnoreCase(newMaintField.getPropertyValue(), oldMaintField.getPropertyValue())
1201 && !Field.HIDDEN.equals(newMaintField.getFieldType())) {
1202 newMaintField.setHighlightField(true);
1203 }
1204
1205 oldMaintField = FieldUtils.fixFieldForForm(oldMaintField, keyFieldNames, KRADConstants.MAINTENANCE_OLD_MAINTAINABLE, maintenanceAction, true, auths, documentStatus, documentInitiatorPrincipalId);
1206 oldFieldsToMerge.add(oldMaintField);
1207 }
1208
1209 newFieldsToMerge.add(newMaintField);
1210
1211 for (Iterator iter = oldFieldsToMerge.iterator(); iter.hasNext();) {
1212 Field element = (Field) iter.next();
1213 meshedFields.add(element);
1214 }
1215
1216 for (Iterator iter = newFieldsToMerge.iterator(); iter.hasNext();) {
1217 Field element = (Field) iter.next();
1218 meshedFields.add(element);
1219 }
1220 }
1221 }
1222 return meshedFields;
1223 }
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237 protected static boolean isLookupFieldLevelHelpEnabled(Class businessObjectClass, String attributeName) {
1238 return false;
1239 }
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253 protected static boolean isLookupFieldLevelHelpDisabled(Class businessObjectClass, String attributeName) {
1254 return false;
1255 }
1256
1257 public static List createAndPopulateFieldsForLookup(List<String> lookupFieldAttributeList, List<String> readOnlyFieldsList, Class businessObjectClass) throws InstantiationException, IllegalAccessException {
1258 List<Field> fields = new ArrayList<Field>();
1259 BusinessObjectEntry boe = (BusinessObjectEntry) getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(businessObjectClass.getName());
1260
1261 Map<String, Boolean> isHiddenMap = new HashMap<String, Boolean>();
1262 Map<String, Boolean> isReadOnlyMap = new HashMap<String, Boolean>();
1263
1264
1265
1266
1267
1268 if(boe.hasLookupDefinition()){
1269 List<FieldDefinition> fieldDefs = boe.getLookupDefinition().getLookupFields();
1270 for(FieldDefinition field : fieldDefs){
1271 isReadOnlyMap.put(field.getAttributeName(), Boolean.valueOf(field.isReadOnly()));
1272 isHiddenMap.put(field.getAttributeName(), Boolean.valueOf(field.isHidden()));
1273 }
1274 }
1275
1276 for( String attributeName : lookupFieldAttributeList )
1277 {
1278 Field field = FieldUtils.getPropertyField(businessObjectClass, attributeName, true);
1279
1280 if(field.isDatePicker() && field.isRanged()) {
1281
1282 Field newDate = createRangeDateField(field);
1283 fields.add(newDate);
1284 }
1285
1286 BusinessObject newBusinessObjectInstance;
1287 if (ExternalizableBusinessObjectUtils.isExternalizableBusinessObjectInterface(businessObjectClass)) {
1288 ModuleService moduleService = getKualiModuleService().getResponsibleModuleService(businessObjectClass);
1289 newBusinessObjectInstance = (BusinessObject) moduleService.createNewObjectFromExternalizableClass(businessObjectClass);
1290 }
1291 else {
1292 newBusinessObjectInstance = (BusinessObject) businessObjectClass.newInstance();
1293 }
1294
1295 field = LookupUtils.setFieldQuickfinder(newBusinessObjectInstance, attributeName, field, lookupFieldAttributeList);
1296 field = LookupUtils.setFieldDirectInquiry(newBusinessObjectInstance, attributeName, field);
1297
1298
1299 if (!Field.MULTISELECT.equals(field.getFieldType())) {
1300 field.setMaxLength(100);
1301 }
1302
1303
1304 if (attributeName.equals(KRADPropertyConstants.ACTIVE) && MutableInactivatable.class.isAssignableFrom(businessObjectClass)) {
1305 field.setPropertyValue(KRADConstants.YES_INDICATOR_VALUE);
1306 field.setDefaultValue(KRADConstants.YES_INDICATOR_VALUE);
1307 }
1308
1309 String defaultValue = getBusinessObjectMetaDataService().getLookupFieldDefaultValue(businessObjectClass, attributeName);
1310 if (defaultValue != null) {
1311 field.setPropertyValue(defaultValue);
1312 field.setDefaultValue(defaultValue);
1313 }
1314
1315 Class defaultValueFinderClass = getBusinessObjectMetaDataService().getLookupFieldDefaultValueFinderClass(businessObjectClass, attributeName);
1316
1317 if (defaultValueFinderClass != null) {
1318 field.setPropertyValue(((ValueFinder) defaultValueFinderClass.newInstance()).getValue());
1319 field.setDefaultValue(((ValueFinder) defaultValueFinderClass.newInstance()).getValue());
1320 }
1321 if ( (readOnlyFieldsList != null && readOnlyFieldsList.contains(field.getPropertyName()))
1322 || ( isReadOnlyMap.containsKey(field.getPropertyName()) && isReadOnlyMap.get(field.getPropertyName()).booleanValue())
1323 ) {
1324 field.setReadOnly(true);
1325 }
1326
1327 populateQuickfinderDefaultsForLookup(businessObjectClass, attributeName, field);
1328
1329 if ((isHiddenMap.containsKey(field.getPropertyName()) && isHiddenMap.get(field.getPropertyName()).booleanValue())) {
1330 field.setFieldType(Field.HIDDEN);
1331 }
1332
1333 boolean triggerOnChange = getBusinessObjectDictionaryService().isLookupFieldTriggerOnChange(businessObjectClass, attributeName);
1334 field.setTriggerOnChange(triggerOnChange);
1335
1336 field.setFieldLevelHelpEnabled(isLookupFieldLevelHelpEnabled(businessObjectClass, attributeName));
1337 field.setFieldLevelHelpDisabled(isLookupFieldLevelHelpDisabled(businessObjectClass, attributeName));
1338
1339 fields.add(field);
1340 }
1341 return fields;
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354 private static void populateQuickfinderDefaultsForLookup(
1355 Class businessObjectClass, String attributeName, Field field)
1356 throws InstantiationException, IllegalAccessException {
1357
1358 String quickfinderParamString = getBusinessObjectMetaDataService().getLookupFieldQuickfinderParameterString(businessObjectClass, attributeName);
1359 Class<? extends ValueFinder> quickfinderParameterFinderClass =
1360 getBusinessObjectMetaDataService().getLookupFieldQuickfinderParameterStringBuilderClass(businessObjectClass, attributeName);
1361 if (quickfinderParameterFinderClass != null) {
1362 quickfinderParamString = quickfinderParameterFinderClass.newInstance().getValue();
1363 }
1364
1365 if (!StringUtils.isEmpty(quickfinderParamString)) {
1366 String [] params = quickfinderParamString.split(",");
1367 if (params != null) for (String param : params) {
1368 if (param.contains(KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER)) {
1369 String[] paramChunks = param.split(KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER, 2);
1370 field.appendLookupParameters(
1371 KRADConstants.LOOKUP_PARAMETER_LITERAL_PREFIX+KRADConstants.LOOKUP_PARAMETER_LITERAL_DELIMITER+
1372 paramChunks[1]+":"+paramChunks[0]);
1373 }
1374 }
1375 }
1376 }
1377
1378
1379
1380
1381
1382
1383
1384 public static Field createRangeDateField(Field field) {
1385 Field newDate = (Field)ObjectUtils.deepCopy(field);
1386 newDate.setFieldLabel(newDate.getFieldLabel()+" "+KRADConstants.LOOKUP_DEFAULT_RANGE_SEARCH_LOWER_BOUND_LABEL);
1387 field.setFieldLabel(field.getFieldLabel()+" "+KRADConstants.LOOKUP_DEFAULT_RANGE_SEARCH_UPPER_BOUND_LABEL);
1388 newDate.setPropertyName(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX+newDate.getPropertyName());
1389 return newDate;
1390 }
1391
1392 private static Field meshContainerFields(Field oldMaintField, Field newMaintField, List keyFieldNames, String maintenanceAction, boolean readOnly, MaintenanceDocumentRestrictions auths, String documentStatus, String documentInitiatorPrincipalId) {
1393 List resultingRows = new ArrayList();
1394 resultingRows.addAll(meshRows(oldMaintField.getContainerRows(), newMaintField.getContainerRows(), keyFieldNames, maintenanceAction, readOnly, auths, documentStatus, documentInitiatorPrincipalId));
1395 Field resultingField = newMaintField;
1396 resultingField.setFieldType(Field.CONTAINER);
1397
1398
1399 resultingField.setContainerElementName(newMaintField.getContainerElementName());
1400 resultingField.setContainerDisplayFields(newMaintField.getContainerDisplayFields());
1401 resultingField.setNumberOfColumnsForCollection(newMaintField.getNumberOfColumnsForCollection());
1402
1403 resultingField.setContainerRows(resultingRows);
1404 List resultingRowsList = newMaintField.getContainerRows();
1405 if (resultingRowsList.size() > 0) {
1406 List resultingFieldsList = ((Row) resultingRowsList.get(0)).getFields();
1407 if (resultingFieldsList.size() > 0) {
1408
1409
1410 String containedFieldName = ((Field) (resultingFieldsList.get(0))).getPropertyName();
1411 resultingField.setPropertyName(containedFieldName.substring(0, containedFieldName.lastIndexOf('.')));
1412 }
1413 }
1414 else {
1415 resultingField.setPropertyName(oldMaintField.getPropertyName());
1416 }
1417 return resultingField;
1418 }
1419
1420
1421
1422
1423
1424
1425
1426
1427 static final public void modifyFieldToSupportMultipleValueLookups(Field field, String parents, MaintainableCollectionDefinition definition) {
1428 field.setMultipleValueLookedUpCollectionName(parents + definition.getName());
1429 field.setMultipleValueLookupClassName(definition.getSourceClassName().getName());
1430 field.setMultipleValueLookupClassLabel(getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(definition.getSourceClassName().getName()).getObjectLabel());
1431 }
1432
1433
1434
1435
1436
1437
1438
1439
1440 static final public boolean isCollectionMultipleLookupEnabled(MaintainableCollectionDefinition definition) {
1441 return definition.getSourceClassName() != null && definition.isIncludeMultipleLookupLine();
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451 public static String scrubWhitespace(String s) {
1452 return s.replaceAll("(\\s)(\\s+)", " ");
1453 }
1454
1455 public static List<Row> convertRemotableAttributeFields(List<RemotableAttributeField> remotableAttributeFields) {
1456 List<Row> rows = new ArrayList<Row>();
1457 for (RemotableAttributeField remotableAttributeField : remotableAttributeFields) {
1458 List<Field> fields = convertRemotableAttributeField(remotableAttributeField);
1459
1460 for (Field field : fields) {
1461 Row row = new Row(field);
1462 rows.add(row);
1463 }
1464 }
1465 return rows;
1466 }
1467
1468 public static List<Field> convertRemotableAttributeField(RemotableAttributeField remotableAttributeField) {
1469
1470 List<Field> fields = constructFieldsForAttributeDefinition(remotableAttributeField);
1471 for (Field field : fields) {
1472 applyControlAttributes(remotableAttributeField, field);
1473 applyLookupAttributes(remotableAttributeField, field);
1474 applyWidgetAttributes(remotableAttributeField, field);
1475
1476
1477 }
1478 return fields;
1479 }
1480
1481 private static List<Field> constructFieldsForAttributeDefinition(RemotableAttributeField remotableAttributeField) {
1482 List<Field> fields = new ArrayList<Field>();
1483 if (remotableAttributeField.getAttributeLookupSettings() != null && remotableAttributeField.getAttributeLookupSettings().isRanged()) {
1484
1485 RemotableAttributeLookupSettings lookupSettings = remotableAttributeField.getAttributeLookupSettings();
1486 String lowerBoundName = lookupSettings.getLowerBoundName();
1487 String upperBoundName = lookupSettings.getUpperBoundName();
1488 String lowerBoundLabel = lookupSettings.getLowerBoundLabel();
1489 String upperBoundLabel = lookupSettings.getUpperBoundLabel();
1490 if (StringUtils.isBlank(lowerBoundName)) {
1491 lowerBoundName = "from_" + remotableAttributeField.getName();
1492 }
1493 if (StringUtils.isBlank(upperBoundName)) {
1494 upperBoundName = "to_" + remotableAttributeField.getName();
1495 }
1496 if (StringUtils.isBlank(lowerBoundLabel)) {
1497 lowerBoundLabel = "From " + remotableAttributeField.getLongLabel();
1498 }
1499 if (StringUtils.isBlank(upperBoundLabel)) {
1500 upperBoundLabel = "To " + remotableAttributeField.getLongLabel();
1501 }
1502
1503 Field lowerField = new Field(lowerBoundName, lowerBoundLabel);
1504 lowerField.setMemberOfRange(true);
1505 lowerField.setAllowInlineRange(false);
1506 lowerField.setRangeFieldInclusive(lookupSettings.isLowerBoundInclusive());
1507 fields.add(lowerField);
1508
1509 Field upperField = new Field(upperBoundName, upperBoundLabel);
1510 upperField.setMemberOfRange(true);
1511 upperField.setAllowInlineRange(false);
1512 upperField.setRangeFieldInclusive(lookupSettings.isUpperBoundInclusive());
1513 fields.add(upperField);
1514 } else {
1515
1516 Field tempField = new Field(remotableAttributeField.getName(), remotableAttributeField.getLongLabel());
1517 tempField.setFieldLabel(remotableAttributeField.getShortLabel());
1518 fields.add(tempField);
1519 }
1520 return fields;
1521 }
1522
1523 public static List<RemotableAttributeField> convertRowsToAttributeFields(List<Row> rows) {
1524 List<RemotableAttributeField> attributeFields = new ArrayList<RemotableAttributeField>();
1525 for (Row row : rows) {
1526 attributeFields.addAll(convertRowToAttributeFields(row));
1527 }
1528 return attributeFields;
1529 }
1530
1531 public static List<RemotableAttributeField> convertRowToAttributeFields(Row row) {
1532 List<RemotableAttributeField> attributeFields = new ArrayList<RemotableAttributeField>();
1533 for (Field field : row.getFields()) {
1534 RemotableAttributeField remotableAttributeField = convertFieldToAttributeField(field);
1535 if (remotableAttributeField != null) {
1536 attributeFields.add(remotableAttributeField);
1537 }
1538 }
1539 return attributeFields;
1540 }
1541
1542 public static RemotableAttributeField convertFieldToAttributeField(Field field) {
1543 RemotableAttributeField.Builder builder = RemotableAttributeField.Builder.create(field.getPropertyName());
1544
1545 List<RemotableAbstractWidget.Builder> widgets = new ArrayList<RemotableAbstractWidget.Builder>();
1546 builder.setDataType(DataType.valueOf(field.getFieldDataType().toUpperCase()));
1547
1548 builder.setShortLabel(field.getFieldLabel());
1549 builder.setLongLabel(field.getMainFieldLabel());
1550 builder.setHelpSummary(field.getFieldHelpSummary());
1551
1552
1553 builder.setForceUpperCase(field.isUpperCase());
1554
1555 builder.setMaxLength(new Integer(field.getMaxLength()));
1556
1557
1558
1559
1560 builder.setRequired(field.isFieldRequired());
1561 builder.setDefaultValues(Collections.singletonList(field.getDefaultValue()));
1562 builder.setControl(FieldUtils.constructControl(field.getFieldType(), field.getFieldValidValues()));
1563
1564 if (field.getHasLookupable()) {
1565 builder.setAttributeLookupSettings(RemotableAttributeLookupSettings.Builder.create());
1566 RemotableQuickFinder.Builder quickfinder =
1567 RemotableQuickFinder.Builder.create(field.getBaseLookupUrl(), field.getQuickFinderClassNameImpl());
1568 quickfinder.setFieldConversions(toMap(field.getFieldConversions()));
1569 quickfinder.setLookupParameters(toMap(field.getLookupParameters()));
1570 widgets.add(quickfinder);
1571 }
1572 if (field.isDatePicker()) {
1573 widgets.add(RemotableDatepicker.Builder.create());
1574 }
1575 if (field.isExpandedTextArea()) {
1576 widgets.add(RemotableTextExpand.Builder.create());
1577 }
1578 builder.setWidgets(widgets);
1579
1580
1581 return builder.build();
1582 }
1583
1584
1585
1586
1587
1588
1589
1590
1591 private static RemotableAbstractControl.Builder constructControl(String type, List<KeyValue> options) {
1592
1593 RemotableAbstractControl.Builder control = null;
1594 Map<String, String> optionMap = new HashMap<String, String>();
1595 if (options != null) {
1596 for (KeyValue option : options) {
1597 optionMap.put(option.getKey(), option.getValue());
1598 }
1599 }
1600 if (Field.TEXT.equals(type) || Field.DATEPICKER.equals(type)) {
1601 control = RemotableTextInput.Builder.create();
1602 } else if (Field.TEXT_AREA.equals(type)) {
1603 control = RemotableTextarea.Builder.create();
1604 } else if (Field.DROPDOWN.equals(type)) {
1605 control = RemotableSelect.Builder.create(optionMap);
1606 } else if (Field.CHECKBOX.equals(type)) {
1607 control = RemotableCheckboxGroup.Builder.create(optionMap);
1608 } else if (Field.RADIO.equals(type)) {
1609 control = RemotableRadioButtonGroup.Builder.create(optionMap);
1610 } else if (Field.HIDDEN.equals(type)) {
1611 control = RemotableHiddenInput.Builder.create();
1612 } else if (Field.MULTIBOX.equals(type)) {
1613 RemotableSelect.Builder builder = RemotableSelect.Builder.create(optionMap);
1614 builder.setMultiple(true);
1615 control = builder;
1616 } else {
1617 throw new IllegalArgumentException("Illegal field type found: " + type);
1618 }
1619 return control;
1620
1621 }
1622
1623 private static void applyControlAttributes(RemotableAttributeField remotableField, Field field) {
1624 Control control = remotableField.getControl();
1625 String fieldType = null;
1626
1627 if (control == null) {
1628 throw new IllegalStateException("Given attribute field with the following name has a null control: " + remotableField.getName());
1629 }
1630 if (control == null || control instanceof RemotableTextInput) {
1631 fieldType = Field.TEXT;
1632 } else if (control instanceof RemotableCheckboxGroup) {
1633 RemotableCheckboxGroup checkbox = (RemotableCheckboxGroup)control;
1634 fieldType = Field.CHECKBOX;
1635 field.setFieldValidValues(FieldUtils.convertMapToKeyValueList(checkbox.getKeyLabels()));
1636 } else if (control instanceof RemotableHiddenInput) {
1637 fieldType = Field.HIDDEN;
1638 } else if (control instanceof RemotablePasswordInput) {
1639 throw new IllegalStateException("Password control not currently supported.");
1640 } else if (control instanceof RemotableRadioButtonGroup) {
1641 fieldType = Field.RADIO;
1642 RemotableRadioButtonGroup radioControl = (RemotableRadioButtonGroup)control;
1643 field.setFieldValidValues(FieldUtils.convertMapToKeyValueList(radioControl.getKeyLabels()));
1644 } else if (control instanceof RemotableSelect) {
1645 RemotableSelect selectControl = (RemotableSelect)control;
1646
1647 field.setFieldValidValues(FieldUtils.convertMapToKeyValueList(selectControl.getKeyLabels()));
1648 if (selectControl.isMultiple()) {
1649 fieldType = Field.MULTISELECT;
1650 } else {
1651 fieldType = Field.DROPDOWN;
1652 }
1653 } else if (control instanceof RemotableTextarea) {
1654 fieldType = Field.TEXT_AREA;
1655 } else {
1656 throw new IllegalArgumentException("Given control type is not supported: " + control.getClass());
1657 }
1658 field.setFieldType(fieldType);
1659 }
1660
1661 private static List<KeyValue> convertMapToKeyValueList(Map<String, String> values) {
1662 ArrayList<KeyValue> validValues = new ArrayList<KeyValue>(values.size());
1663 for (Map.Entry<String, String> entry : values.entrySet()) {
1664 validValues.add(new ConcreteKeyValue(entry.getKey(), entry.getValue()));
1665 }
1666 return validValues;
1667 }
1668
1669 private static void applyLookupAttributes(RemotableAttributeField remotableField, Field field) {
1670 RemotableAttributeLookupSettings lookupSettings = remotableField.getAttributeLookupSettings();
1671 if (lookupSettings != null) {
1672 field.setColumnVisible(lookupSettings.isInResults());
1673 if (!lookupSettings.isInCriteria()) {
1674 field.setFieldType(Field.HIDDEN);
1675 }
1676 }
1677 }
1678
1679 private static void applyWidgetAttributes(RemotableAttributeField remotableField, Field field) {
1680 Collection<? extends RemotableAbstractWidget> widgets = remotableField.getWidgets();
1681
1682 for (RemotableAbstractWidget widget : widgets) {
1683
1684 if (widget instanceof RemotableQuickFinder) {
1685 field.setQuickFinderClassNameImpl(((RemotableQuickFinder)widget).getDataObjectClass());
1686 field.setBaseLookupUrl(((RemotableQuickFinder)widget).getBaseLookupUrl());
1687 field.setLookupParameters(((RemotableQuickFinder)widget).getLookupParameters());
1688 field.setFieldConversions(((RemotableQuickFinder)widget).getFieldConversions());
1689 } else if (widget instanceof RemotableDatepicker) {
1690 field.setDatePicker(true);
1691 } else if (widget instanceof RemotableTextExpand) {
1692 field.setExpandedTextArea(true);
1693 }
1694
1695 }
1696 }
1697
1698 public static Column constructColumnFromAttributeField(RemotableAttributeField attributeField) {
1699 if (attributeField == null) {
1700 throw new IllegalArgumentException("attributeField was null");
1701 }
1702 DataType dataType = DataType.STRING;
1703 if (attributeField.getDataType() != null) {
1704 dataType = attributeField.getDataType();
1705 }
1706 Column column = new Column();
1707 String columnTitle = "";
1708 if (StringUtils.isBlank(attributeField.getShortLabel())) {
1709 if (StringUtils.isBlank(attributeField.getLongLabel())) {
1710 columnTitle = attributeField.getName();
1711 } else {
1712 columnTitle = attributeField.getLongLabel();
1713 }
1714 } else {
1715 columnTitle = attributeField.getShortLabel();
1716 }
1717 column.setColumnTitle(columnTitle);
1718 column.setSortable(Boolean.TRUE.toString());
1719
1720 if (attributeField.getMaxLength() != null) {
1721 column.setMaxLength(attributeField.getMaxLength());
1722 }
1723 column.setPropertyName(attributeField.getName());
1724 if (attributeField.getDataType() == DataType.MARKUP) {
1725 column.setEscapeXMLValue(false);
1726 } else {
1727 column.setEscapeXMLValue(true);
1728 }
1729 column.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(dataType.getClass()));
1730 column.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(dataType.getClass()));
1731 column.setFormatter(FieldUtils.getFormatterForDataType(dataType));
1732 return column;
1733 }
1734
1735 public static List<Column> constructColumnsFromAttributeFields(List<RemotableAttributeField> attributeFields) {
1736 List<Column> attributeColumns = new ArrayList<Column>();
1737 if (attributeFields != null) {
1738 for (RemotableAttributeField attributeField : attributeFields) {
1739 attributeColumns.add(constructColumnFromAttributeField(attributeField));
1740 }
1741 }
1742 return attributeColumns;
1743 }
1744
1745 public static Formatter getFormatterForDataType(DataType dataType) {
1746 return Formatter.getFormatter(dataType.getType());
1747 }
1748
1749 private static Map<String, String> toMap(String s) {
1750 if (StringUtils.isBlank(s)) {
1751 return Collections.emptyMap();
1752 }
1753 final Map<String, String> map = new HashMap<String, String>();
1754 for (String string : s.split(",")) {
1755 String [] keyVal = string.split(":");
1756 map.put(keyVal[0], keyVal[1]);
1757 }
1758 return Collections.unmodifiableMap(map);
1759 }
1760
1761 private static DataDictionaryService getDataDictionaryService() {
1762 if (dataDictionaryService == null) {
1763 dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
1764 }
1765 return dataDictionaryService;
1766 }
1767
1768 private static BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
1769 if (businessObjectMetaDataService == null) {
1770 businessObjectMetaDataService = KNSServiceLocator.getBusinessObjectMetaDataService();
1771 }
1772 return businessObjectMetaDataService;
1773 }
1774
1775 private static BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
1776 if (businessObjectDictionaryService == null) {
1777 businessObjectDictionaryService = KRADServiceLocatorWeb.getBusinessObjectDictionaryService();
1778 }
1779 return businessObjectDictionaryService;
1780 }
1781
1782 private static KualiModuleService getKualiModuleService() {
1783 if (kualiModuleService == null) {
1784 kualiModuleService = KRADServiceLocatorWeb.getKualiModuleService();
1785 }
1786 return kualiModuleService;
1787 }
1788 }