View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.web.ui;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.util.ClassLoaderUtils;
20  import org.kuali.rice.core.api.util.KeyValue;
21  import org.kuali.rice.core.web.format.Formatter;
22  import org.kuali.rice.kns.datadictionary.CollectionDefinitionI;
23  import org.kuali.rice.kns.datadictionary.FieldDefinition;
24  import org.kuali.rice.kns.datadictionary.FieldDefinitionI;
25  import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
26  import org.kuali.rice.kns.datadictionary.MaintainableFieldDefinition;
27  import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
28  import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
29  import org.kuali.rice.kns.lookup.LookupUtils;
30  import org.kuali.rice.kns.maintenance.Maintainable;
31  import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
32  import org.kuali.rice.kns.service.KNSServiceLocator;
33  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
34  import org.kuali.rice.kns.util.FieldUtils;
35  import org.kuali.rice.kns.util.MaintenanceUtils;
36  import org.kuali.rice.kns.util.WebUtils;
37  import org.kuali.rice.krad.bo.BusinessObject;
38  import org.kuali.rice.krad.datadictionary.control.ControlDefinition;
39  import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
40  import org.kuali.rice.krad.keyvalues.PersistableBusinessObjectValuesFinder;
41  import org.kuali.rice.krad.service.DataDictionaryService;
42  import org.kuali.rice.krad.service.KRADServiceLocator;
43  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
44  import org.kuali.rice.krad.service.PersistenceStructureService;
45  import org.kuali.rice.krad.util.KRADConstants;
46  import org.kuali.rice.krad.util.ObjectUtils;
47  
48  import java.util.ArrayList;
49  import java.util.Collection;
50  import java.util.List;
51  import java.util.Set;
52  
53  @Deprecated
54  public class FieldBridge {
55      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(FieldBridge.class);
56      private static DataDictionaryService dataDictionaryService;
57      private static PersistenceStructureService persistenceStructureService;
58      private static BusinessObjectDictionaryService businessObjectDictionaryService;
59      private static MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
60  
61      /**
62       * Sets additional properties for MaintainableField(s)
63       *
64       * @param field The field to populate.
65       * @param definition The DD specification for the field.
66       */
67      public static final void setupField(Field field, FieldDefinitionI definition, Set<String> conditionallyRequiredMaintenanceFields) {
68          if (definition instanceof MaintainableFieldDefinition) {
69              MaintainableFieldDefinition maintainableFieldDefinition = ((MaintainableFieldDefinition) definition);
70              
71              field.setFieldRequired(maintainableFieldDefinition.isRequired());
72              field.setReadOnly(maintainableFieldDefinition.isUnconditionallyReadOnly());
73              if (maintainableFieldDefinition.isLookupReadOnly()) {
74              	field.setFieldType(Field.LOOKUP_READONLY);
75              }
76  
77              // set onblur and callback functions
78              if (StringUtils.isNotBlank(maintainableFieldDefinition.getWebUILeaveFieldFunction())) {
79                  field.setWebOnBlurHandler(maintainableFieldDefinition.getWebUILeaveFieldFunction());
80              }
81  
82              if (StringUtils.isNotBlank(maintainableFieldDefinition.getWebUILeaveFieldCallbackFunction())) {
83                  field.setWebOnBlurHandlerCallback(maintainableFieldDefinition.getWebUILeaveFieldCallbackFunction());
84              }
85  
86              if (maintainableFieldDefinition.getWebUILeaveFieldFunctionParameters()!=null) {
87                  field.setWebUILeaveFieldFunctionParameters(maintainableFieldDefinition.getWebUILeaveFieldFunctionParameters());
88              }
89              
90  			if (StringUtils.isNotBlank(maintainableFieldDefinition.getAlternateDisplayAttributeName())) {
91  				field.setAlternateDisplayPropertyName(maintainableFieldDefinition.getAlternateDisplayAttributeName());
92  			}
93  
94  			if (StringUtils.isNotBlank(maintainableFieldDefinition.getAdditionalDisplayAttributeName())) {
95  				field.setAdditionalDisplayPropertyName(maintainableFieldDefinition.getAdditionalDisplayAttributeName());
96  			}
97              
98              if (conditionallyRequiredMaintenanceFields != null && conditionallyRequiredMaintenanceFields.contains(field.getPropertyName())) {
99              	field.setFieldRequired(true);
100             }
101             
102             if (((MaintainableFieldDefinition) definition).isTriggerOnChange()) {
103             	field.setTriggerOnChange(true);
104             }
105         }
106     }
107 
108     /**
109 	 * Uses reflection to populate the rows of the inquiry from the business
110 	 * object value. Also formats if needed.
111      *
112 	 * @param field
113 	 *            The Field to populate.
114 	 * @param bo
115 	 *            The BusinessObject from which the Field will be popualated.
116      */
117     public static final void populateFieldFromBusinessObject(Field field, BusinessObject bo) {
118         if (bo == null) {
119             throw new RuntimeException("Inquiry Business object is null.");
120         }
121 
122         field.setReadOnly(true); // inquiry fields are always read only
123 
124         Formatter formatter = field.getFormatter();
125         String propertyName = field.getPropertyName();
126 
127         // get the field type for the property
128 		ControlDefinition fieldControl = getDataDictionaryService().getAttributeControlDefinition(bo.getClass(),
129 				propertyName);
130         try {
131             Object prop = ObjectUtils.getPropertyValue(bo, field.getPropertyName());
132 
133 			// for select fields, display the associated label (unless we are
134 			// already display an additonal attribute)
135 			String propValue = KRADConstants.EMPTY_STRING;
136 			if (fieldControl != null && fieldControl.isSelect()
137 					&& StringUtils.isBlank(field.getAdditionalDisplayPropertyName())
138 					&& StringUtils.isBlank(field.getAlternateDisplayPropertyName())) {
139 				Class<? extends KeyValuesFinder> keyValuesFinderName = ClassLoaderUtils.getClass(fieldControl.getValuesFinderClass(), KeyValuesFinder.class);
140                 KeyValuesFinder finder = keyValuesFinderName.newInstance();
141 
142                 propValue = lookupFinderValue(fieldControl, prop, finder);
143             } else {
144 				propValue = ObjectUtils.getFormattedPropertyValue(bo, field.getPropertyName(), formatter);
145                     }
146 			field.setPropertyValue(propValue);
147 			
148 			// set additional or alternate display property values if property
149 			// name is specified
150 			if (StringUtils.isNotBlank(field.getAlternateDisplayPropertyName())) {
151 				String alternatePropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(bo, field
152 						.getAlternateDisplayPropertyName());
153 				field.setAlternateDisplayPropertyValue(alternatePropertyValue);
154                 }
155 
156 			if (StringUtils.isNotBlank(field.getAdditionalDisplayPropertyName())) {
157 				String additionalPropertyValue = ObjectUtils.getFormattedPropertyValueUsingDataDictionary(bo, field
158 						.getAdditionalDisplayPropertyName());
159 				field.setAdditionalDisplayPropertyValue(additionalPropertyValue);
160             }
161 
162 			// for user fields, attempt to pull the principal ID and person's
163 			// name from the source object
164             if ( fieldControl != null && fieldControl.isKualiUser() ) {
165             	// this is supplemental, so catch and log any errors 
166             	try {
167             		if ( StringUtils.isNotBlank(field.getUniversalIdAttributeName()) ) {
168             			Object principalId = ObjectUtils.getNestedValue(bo, field.getUniversalIdAttributeName());
169             			if ( principalId != null ) {
170             				field.setUniversalIdValue(principalId.toString());
171             			}
172             		}
173             		if ( StringUtils.isNotBlank(field.getPersonNameAttributeName()) ) {
174             			Object personName = ObjectUtils.getNestedValue(bo, field.getPersonNameAttributeName());
175             			if ( personName != null ) {
176             				field.setPersonNameValue( personName.toString() );
177             			}
178             		}
179             	} catch ( Exception ex ) {
180             		LOG.warn( "Unable to get principal ID or person name property in FieldBridge.", ex );
181             	}
182             }
183             if (fieldControl != null && fieldControl.isFile()) {
184                 if (Field.FILE.equals(field.getFieldType())) {
185                     Object fileName = ObjectUtils.getNestedValue(bo, KRADConstants.BO_ATTACHMENT_FILE_NAME);
186                     Object fileType = ObjectUtils.getNestedValue(bo, KRADConstants.BO_ATTACHMENT_FILE_CONTENT_TYPE);
187                     field.setImageSrc(WebUtils.getAttachmentImageForUrl((String) fileType));
188                     field.setPropertyValue(fileName);
189                 }
190             }
191             FieldUtils.setInquiryURL(field, bo, propertyName);
192 		} catch (InstantiationException e) {
193             LOG.error("Unable to get instance of KeyValuesFinder: " + e.getMessage());
194             throw new RuntimeException("Unable to get instance of KeyValuesFinder: " + e.getMessage());
195 		} catch (ClassNotFoundException e) {
196 			LOG.error("Unable to get instance of KeyValuesFinder: " + e.getMessage());
197             throw new RuntimeException("Unable to get instance of KeyValuesFinder: " + e.getMessage());
198 		} catch (IllegalAccessException e) {
199             LOG.error("Unable to set columns: " + e.getMessage());
200             throw new RuntimeException("Unable to set columns: " + e.getMessage());
201         }
202 
203     }
204 
205     /**
206      * This method looks up a value in a finder class.
207      * @param fieldControl the type of web control that is associated with this field.
208      * @param prop the property to look up - either a property name as a String, or a referenced object
209      * @param finder finder to look the value up in
210      * @return the value that was returned from the lookup
211      */
212     private static String lookupFinderValue(ControlDefinition fieldControl, Object prop, KeyValuesFinder finder) {
213         String propValue = null;
214 
215         // KULRICE-1808 : PersistableBusinessObjectValuesFinder is not working for inquiries that have child objects with ValuesFinder populated select lists
216         if (finder instanceof PersistableBusinessObjectValuesFinder) {
217             ((PersistableBusinessObjectValuesFinder) finder).setBusinessObjectClass(ClassLoaderUtils.getClass(fieldControl.getBusinessObjectClass()));
218             ((PersistableBusinessObjectValuesFinder) finder).setKeyAttributeName(fieldControl.getKeyAttribute());
219             ((PersistableBusinessObjectValuesFinder) finder).setLabelAttributeName(fieldControl.getLabelAttribute());
220             if (fieldControl.getIncludeBlankRow() != null) {
221             	((PersistableBusinessObjectValuesFinder) finder).setIncludeBlankRow(fieldControl.getIncludeBlankRow());
222             }
223             ((PersistableBusinessObjectValuesFinder) finder).setIncludeKeyInDescription(fieldControl.getIncludeKeyInLabel());
224         }
225         List<KeyValue> keyValues = finder.getKeyValues();
226         propValue = getPropertyValueFromList(prop, keyValues);
227         if(propValue==null) {
228 			propValue = lookupInactiveFinderValue(prop, finder);
229 		}
230         return propValue;
231     }
232     
233     private static String lookupInactiveFinderValue(Object property, KeyValuesFinder finder){
234     	List<KeyValue> keyValues = finder.getKeyValues(false);
235     	return getPropertyValueFromList(property, keyValues);
236     	
237     }
238     
239     private static String getPropertyValueFromList(Object property, List<KeyValue> keyValues){
240     	String propertyValue = null;
241         if (property != null) {
242             for (Object element2 : keyValues) {
243                 KeyValue element = (KeyValue) element2;
244                 if (element.getKey().toString().equals(property.toString())) {
245                     propertyValue = element.getValue();
246                     break;
247                 }
248             }
249         }
250         return propertyValue;
251     }
252     
253     /**
254      * Determines whether field level help is enabled for the field corresponding to the dataObjectClass and attribute name
255      *
256      * If this value is true, then the field level help will be enabled.
257      * If false, then whether a field is enabled is determined by the value returned by {@link #isMaintenanceFieldLevelHelpDisabled(Maintainable, MaintainableFieldDefinition)}
258      * and the system-wide parameter setting.  Note that if a field is read-only, that may cause field-level help to not be rendered.
259      *
260      * @param businessObjectClass the looked up class
261      * @param attributeName the attribute for the field
262      * @return true if field level help is enabled, false if the value of this method should NOT be used to determine whether this method's return value
263      * affects the enablement of field level help
264      */
265     protected static boolean isMaintenanceFieldLevelHelpEnabled(Maintainable m, MaintainableFieldDefinition fieldDefinition) {
266         if ( fieldDefinition != null ) {
267             if ( fieldDefinition.isShowFieldLevelHelp() != null && fieldDefinition.isShowFieldLevelHelp() ) {
268                 return true;
269             }
270         }
271         return false;
272     }
273 
274     /**
275      * Determines whether field level help is disabled for the field corresponding to the dataObjectClass and attribute name
276      *
277      * If this value is true and {@link #isMaintenanceFieldLevelHelpEnabled(Maintainable, MaintainableFieldDefinition)} returns false,
278      * then the field level help will not be rendered.  If both this and {@link #isMaintenanceFieldLevelHelpEnabled(Maintainable, MaintainableFieldDefinition)} return false,
279      * then the system-wide setting will determine whether field level help is enabled.  Note that if a field is read-only, that may cause
280      * field-level help to not be rendered.
281      *
282      * @param businessObjectClass the looked up class
283      * @param attributeName the attribute for the field
284      * @return true if field level help is disabled, false if the value of this method should NOT be used to determine whether this method's return value
285      * affects the enablement of field level help
286      */
287     protected static boolean isMaintenanceFieldLevelHelpDisabled(Maintainable m, MaintainableFieldDefinition fieldDefinition) {
288         if ( fieldDefinition != null ) {
289             if ( fieldDefinition.isShowFieldLevelHelp() != null && !fieldDefinition.isShowFieldLevelHelp() ) {
290                 return true;
291             }
292         }
293         return false;
294     }
295 
296     /**
297      * This method creates a Field for display on a Maintenance Document.
298      *
299      * @param id The DD definition for the Field (can be a Collection).
300      * @param sd The DD definition for the Section in which the field will be displayed.
301      * @param o The BusinessObject will be populated from this BO.
302      * @param m
303      * @param s The Section in which the Field will be displayed.
304      * @param autoFillDefaultValues Should default values be filled in?
305      * @param autoFillBlankRequiredValues Should values be filled in for fields that are required but which were left blank when submitting the form from the UI?
306      * @param displayedFieldNames What fields are being displayed on the form in the UI?
307      *
308      * @return
309      *
310      * @throws InstantiationException
311      * @throws IllegalAccessException
312      */
313     public static final Field toField(MaintainableItemDefinition id, MaintainableSectionDefinition sd, BusinessObject o, Maintainable m, Section s, List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields) throws InstantiationException, IllegalAccessException {
314         Field field = new Field();
315 
316         // if FieldDefiniton, simply add a Field UI object
317         if (id instanceof MaintainableFieldDefinition) {
318             MaintainableFieldDefinition maintainableFieldDefinition = (MaintainableFieldDefinition) id;
319             field = FieldUtils.getPropertyField(o.getClass(), maintainableFieldDefinition.getName(), false);
320 
321 			boolean translateCodes = getMaintenanceDocumentDictionaryService().translateCodes(o.getClass());
322 			if (translateCodes) {
323 				FieldUtils.setAdditionalDisplayPropertyForCodes(o.getClass(), field.getPropertyName(), field);
324 			}
325 
326             setupField(field, maintainableFieldDefinition, conditionallyRequiredMaintenanceFields);
327 
328             MaintenanceUtils.setFieldQuickfinder(o, field.getPropertyName(), maintainableFieldDefinition, field, displayedFieldNames, m);
329             MaintenanceUtils.setFieldDirectInquiry(o, field.getPropertyName(), maintainableFieldDefinition, field, displayedFieldNames);
330 
331             // set default value
332             //TODO St. Ailish says review this. A question was raised on 11-16-2006 Tuscon meeting as to why this is done here and not in the formatter.
333             /*if (autoFillDefaultValues) {
334                 Object defaultValue = maintainableFieldDefinition.getDefaultValue();
335                 if (defaultValue != null) {
336                     if (defaultValue.toString().equals("true")) {
337                         defaultValue = "Yes";
338                     }
339                     else if (defaultValue.toString().equals("false")) {
340                         defaultValue = "No";
341                     }
342                     field.setPropertyValue(defaultValue);
343                 }
344 
345                 Class defaultValueFinderClass = maintainableFieldDefinition.getDefaultValueFinderClass();
346                 if (defaultValueFinderClass != null) {
347                     field.setPropertyValue(((ValueFinder) defaultValueFinderClass.newInstance()).getValue());
348                 }
349             }
350 
351             // if this flag is set, and the current field is required, and readonly, and blank, use the
352             // defaultValueFinder if one exists
353             if (autoFillBlankRequiredValues) {
354                 if ( maintainableFieldDefinition.isRequired() && maintainableFieldDefinition.isUnconditionallyReadOnly() ) {
355                     if ( StringUtils.isBlank( field.getPropertyValue() ) ) {
356                         Class defaultValueFinderClass = maintainableFieldDefinition.getDefaultValueFinderClass();
357                         if (defaultValueFinderClass != null) {
358                             field.setPropertyValue(((ValueFinder) defaultValueFinderClass.newInstance()).getValue());
359                         }
360                     }
361                 }
362             }
363 			*/
364             field.setFieldLevelHelpEnabled(isMaintenanceFieldLevelHelpEnabled(m, maintainableFieldDefinition));
365             field.setFieldLevelHelpDisabled(isMaintenanceFieldLevelHelpDisabled(m, maintainableFieldDefinition));
366             field.setFieldLevelHelpUrl(maintainableFieldDefinition.getFieldLevelHelpUrl());
367         }
368 
369         return field;
370 
371     }
372 
373     /**
374      * This method will return a new form for adding in a BO for a collection.
375      * This should be customized in a subclass so the default behavior is to return nothing.
376      *
377      * @param collectionDefinition The DD definition for the Collection.
378      * @param o The BusinessObject form which the new Fields will be populated.
379      * @param document MaintenanceDocument instance which we ar building fields for
380      * @param m
381      * @param displayedFieldNames What Fields are being displayed on the form in the UI?
382      * @param containerRowErrorKey The error key for the Container/Collection used for displaying error messages.
383      * @param parents
384      * @param hideAdd Should the add line be hidden when displaying this Collection/Container in the UI?
385      * @param numberOfColumns How many columns the Fields in the Collection will be split into when displaying them in the UI.
386      *
387      * @return The List of new Fields.
388      */
389     public static final List<Field> getNewFormFields(CollectionDefinitionI collectionDefinition, BusinessObject o, Maintainable m, List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields, StringBuffer containerRowErrorKey, String parents, boolean hideAdd, int numberOfColumns) {
390         LOG.debug( "getNewFormFields" );
391         String collName = collectionDefinition.getName();
392 
393         List<Field> collFields = new ArrayList<Field>();
394         Collection<? extends FieldDefinitionI> collectionFields;
395         //Class boClass = collectionDefinition.getDataObjectClass();
396         BusinessObject collBO = null;
397         try {
398             collectionFields = collectionDefinition.getFields();
399             collBO = m.getNewCollectionLine(parents + collName);
400 
401             if ( LOG.isDebugEnabled() ) {
402                 LOG.debug( "newBO for add line: " + collBO );
403             }
404 
405             for ( FieldDefinitionI fieldDefinition : collectionFields  ) {
406                 // construct Field UI object from definition
407                 Field collField = FieldUtils.getPropertyField(collectionDefinition.getBusinessObjectClass(), fieldDefinition.getName(), false);
408 
409                 if (fieldDefinition instanceof MaintainableFieldDefinition) {
410                     setupField(collField, fieldDefinition, conditionallyRequiredMaintenanceFields);
411                 }
412                 //generate the error key for the add row
413                 String[] nameParts = StringUtils.split(collField.getPropertyName(), ".");
414                 String fieldErrorKey = KRADConstants.MAINTENANCE_NEW_MAINTAINABLE + KRADConstants.ADD_PREFIX + ".";
415                 fieldErrorKey += collName + ".";
416                 for (int i = 0; i < nameParts.length; i++) {
417                     fieldErrorKey += nameParts[i];
418                     containerRowErrorKey.append(fieldErrorKey);
419                     if (i < nameParts.length) {
420                         fieldErrorKey += ".";
421                         containerRowErrorKey.append(",");
422                     }
423                 }
424 
425                 //  set the QuickFinderClass
426                 BusinessObject collectionBoInstance = collectionDefinition.getBusinessObjectClass().newInstance();
427                 FieldUtils.setInquiryURL(collField, collectionBoInstance, fieldDefinition.getName());
428                 if (collectionDefinition instanceof MaintainableCollectionDefinition) {
429                     MaintenanceUtils.setFieldQuickfinder(collectionBoInstance, parents+collectionDefinition.getName(), true, 0, fieldDefinition.getName(), collField, displayedFieldNames, m, (MaintainableFieldDefinition) fieldDefinition);
430                     MaintenanceUtils
431                             .setFieldDirectInquiry(collectionBoInstance, parents + collectionDefinition.getName(), true,
432                                     0, fieldDefinition.getName(), collField, displayedFieldNames, m,
433                                     (MaintainableFieldDefinition) fieldDefinition);
434                 }
435                 else {
436                     LookupUtils.setFieldQuickfinder(collectionBoInstance, parents+collectionDefinition.getName(), true, 0, fieldDefinition.getName(), collField, displayedFieldNames, m);
437                     LookupUtils.setFieldDirectInquiry(collectionBoInstance, fieldDefinition.getName(), collField);
438                 }
439 
440                 collFields.add(collField);
441             }
442 
443         } catch (InstantiationException e) {
444             LOG.error("Unable to create instance of object class" + e.getMessage());
445             throw new RuntimeException("Unable to create instance of object class" + e.getMessage());
446         } catch (IllegalAccessException e) {
447             LOG.error("Unable to create instance of object class" + e.getMessage());
448             throw new RuntimeException("Unable to create instance of object class" + e.getMessage());
449         }
450 
451         // populate field values from business object
452         collFields = FieldUtils.populateFieldsFromBusinessObject(collFields,collBO);
453 
454         // need to append the prefix afterwards since the population command (above)
455         // does not handle the prefixes on the property names
456         for ( Field field : collFields ) {
457             // prefix name for add line
458             field.setPropertyName(KRADConstants.MAINTENANCE_ADD_PREFIX + parents + collectionDefinition.getName() + "." + field.getPropertyName());
459         }
460         LOG.debug("Error Key for section " + collectionDefinition.getName() + " : " + containerRowErrorKey.toString());
461 
462         
463         collFields = constructContainerField(collectionDefinition, parents, o, hideAdd, numberOfColumns, collName, collFields);
464 
465         return collFields;
466     }
467 
468     /**
469      * 
470      * This method handles setting up a container field not including the add fields
471      * 
472      * @param collectionDefinition
473      * @param parents
474      * @param o
475      * @param hideAdd
476      * @param numberOfColumns
477      * @param collName
478      * @param collFields
479      * @return
480      */
481     public static List<Field> constructContainerField(CollectionDefinitionI collectionDefinition, String parents, BusinessObject o, boolean hideAdd, int numberOfColumns, String collName, List<Field> collFields) {
482         // get label for collection
483         String collectionLabel = getDataDictionaryService().getCollectionLabel(o.getClass(), collectionDefinition.getName());
484 
485         // retrieve the summary label either from the override or from the DD
486         String collectionElementLabel = collectionDefinition.getSummaryTitle();
487         if(StringUtils.isEmpty(collectionElementLabel)){
488             collectionElementLabel = getDataDictionaryService().getCollectionElementLabel(o.getClass().getName(), collectionDefinition.getName(),collectionDefinition.getBusinessObjectClass());
489         }
490 
491         // container field
492         Field containerField;
493         containerField = FieldUtils.constructContainerField(collName, collectionLabel, collFields, numberOfColumns);
494         if(StringUtils.isNotEmpty(collectionElementLabel)) {
495             containerField.setContainerElementName(collectionElementLabel);
496         }
497         collFields = new ArrayList();
498         collFields.add(containerField);
499 
500         // field button for adding lines
501         if(!hideAdd  && collectionDefinition.getIncludeAddLine()) {
502             Field field = new Field();
503 
504             String addButtonName = KRADConstants.DISPATCH_REQUEST_PARAMETER + "." + KRADConstants.ADD_LINE_METHOD + "." + parents + collectionDefinition.getName() + "." + KRADConstants.METHOD_TO_CALL_BOPARM_LEFT_DEL + collectionDefinition.getBusinessObjectClass().getName() + KRADConstants.METHOD_TO_CALL_BOPARM_RIGHT_DEL;
505             field.setPropertyName(addButtonName);
506             field.setFieldType(Field.IMAGE_SUBMIT);
507             field.setPropertyValue("images/tinybutton-add1.gif");
508             // collFields.add(field);
509             containerField.getContainerRows().add(new Row(field));
510         }
511 
512         if (collectionDefinition instanceof MaintainableCollectionDefinition) {
513             if (FieldUtils.isCollectionMultipleLookupEnabled((MaintainableCollectionDefinition) collectionDefinition)) {
514                 FieldUtils.modifyFieldToSupportMultipleValueLookups(containerField, parents, (MaintainableCollectionDefinition) collectionDefinition);
515             }
516         }
517 
518         return collFields;
519     }
520 
521     /**
522      * Call getNewFormFields with no parents.
523      *
524      * @see #getNewFormFields(org.kuali.rice.kns.datadictionary.CollectionDefinitionI, BusinessObject, Maintainable, List, StringBuffer, String, boolean, int)
525      */
526     public static final List<Field> getNewFormFields(MaintainableCollectionDefinition collectionDefinition, BusinessObject o, Maintainable m, List<String> displayedFieldNames, Set<String> conditionallyRequiredMaintenanceFields, StringBuffer containerRowErrorKey, int numberOfColumns) {
527         String parent = "";
528         return getNewFormFields(collectionDefinition, o, m, displayedFieldNames, conditionallyRequiredMaintenanceFields, containerRowErrorKey, parent, false, numberOfColumns);
529     }
530 
531     /**
532      * Create a Field for display on an Inquiry screen.
533      *
534      * @param d The DD definition for the Field.
535      * @param o The BusinessObject from which the Field will be populated.
536      * @param s The Section in which the Field will be displayed.
537      *
538      * @return The populated Field.
539      */
540     public static Field toField(FieldDefinition d, BusinessObject o, Section s) {
541         Field field = FieldUtils.getPropertyField(o.getClass(), d.getAttributeName(), false);
542         
543         FieldUtils.setInquiryURL(field, o, field.getPropertyName());
544 
545 		String alternateDisplayPropertyName = getBusinessObjectDictionaryService()
546 				.getInquiryFieldAlternateDisplayAttributeName(o.getClass(), d.getAttributeName());
547 		if (StringUtils.isNotBlank(alternateDisplayPropertyName)) {
548 			field.setAlternateDisplayPropertyName(alternateDisplayPropertyName);
549 		}
550 
551 		String additionalDisplayPropertyName = getBusinessObjectDictionaryService()
552 				.getInquiryFieldAdditionalDisplayAttributeName(o.getClass(), d.getAttributeName());
553 		if (StringUtils.isNotBlank(additionalDisplayPropertyName)) {
554 			field.setAdditionalDisplayPropertyName(additionalDisplayPropertyName);
555 		}
556 		else {
557 			boolean translateCodes = getBusinessObjectDictionaryService().tranlateCodesInInquiry(o.getClass());
558 			if (translateCodes) {
559 				FieldUtils.setAdditionalDisplayPropertyForCodes(o.getClass(), d.getAttributeName(), field);
560 			}
561 		}
562 
563         populateFieldFromBusinessObject(field, o);
564 
565         return field;
566     }
567 
568 	public static DataDictionaryService getDataDictionaryService() {
569     	if (dataDictionaryService == null) {
570     		dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
571     	}
572 		return dataDictionaryService;
573 	}
574 
575 	public static PersistenceStructureService getPersistenceStructureService() {
576     	if (persistenceStructureService == null) {
577     		persistenceStructureService = KRADServiceLocator.getPersistenceStructureService();
578     	}
579 		return persistenceStructureService;
580 	}
581 
582 	public static BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
583     	if (businessObjectDictionaryService == null) {
584     		businessObjectDictionaryService = KNSServiceLocator.getBusinessObjectDictionaryService();
585     	}
586 		return businessObjectDictionaryService; 
587 	}
588 	
589 	public static MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
590     	if (maintenanceDocumentDictionaryService == null) {
591     		maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
592     	}
593 		return maintenanceDocumentDictionaryService; 
594 	}
595 
596 }
597