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