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