View Javadoc

1   /**
2    * Copyright 2005-2011 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.kew.rule.bo;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.uif.RemotableAttributeField;
20  import org.kuali.rice.core.api.uif.RemotableCheckboxGroup;
21  import org.kuali.rice.core.api.uif.RemotableRadioButtonGroup;
22  import org.kuali.rice.core.api.uif.RemotableSelect;
23  import org.kuali.rice.core.api.uif.RemotableTextInput;
24  import org.kuali.rice.core.api.util.ConcreteKeyValue;
25  import org.kuali.rice.core.api.util.KeyValue;
26  import org.kuali.rice.core.api.util.RiceKeyConstants;
27  import org.kuali.rice.core.web.format.BooleanFormatter;
28  import org.kuali.rice.core.web.format.CollectionFormatter;
29  import org.kuali.rice.core.web.format.DateFormatter;
30  import org.kuali.rice.core.web.format.Formatter;
31  import org.kuali.rice.kew.api.KewApiServiceLocator;
32  import org.kuali.rice.kew.api.rule.RuleTemplate;
33  import org.kuali.rice.kew.api.rule.RuleTemplateAttribute;
34  import org.kuali.rice.kew.api.validation.ValidationResults;
35  import org.kuali.rice.kew.framework.KewFrameworkServiceLocator;
36  import org.kuali.rice.kew.framework.rule.attribute.WorkflowRuleAttributeHandlerService;
37  import org.kuali.rice.kew.lookupable.MyColumns;
38  import org.kuali.rice.kew.rule.RuleBaseValues;
39  import org.kuali.rice.kew.rule.RuleDelegationBo;
40  import org.kuali.rice.kew.rule.service.RuleDelegationService;
41  import org.kuali.rice.kew.rule.service.RuleTemplateService;
42  import org.kuali.rice.kew.service.KEWServiceLocator;
43  import org.kuali.rice.kew.api.KewApiConstants;
44  import org.kuali.rice.kim.api.KimConstants;
45  import org.kuali.rice.kim.api.group.Group;
46  import org.kuali.rice.kim.api.group.GroupService;
47  import org.kuali.rice.kim.api.identity.Person;
48  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
49  import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
50  import org.kuali.rice.kns.lookup.HtmlData;
51  import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
52  import org.kuali.rice.kns.util.FieldUtils;
53  import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
54  import org.kuali.rice.kns.web.struts.form.LookupForm;
55  import org.kuali.rice.kns.web.ui.Column;
56  import org.kuali.rice.kns.web.ui.Field;
57  import org.kuali.rice.kns.web.ui.ResultRow;
58  import org.kuali.rice.kns.web.ui.Row;
59  import org.kuali.rice.krad.bo.BusinessObject;
60  import org.kuali.rice.krad.bo.PersistableBusinessObject;
61  import org.kuali.rice.krad.exception.ValidationException;
62  import org.kuali.rice.krad.util.GlobalVariables;
63  import org.kuali.rice.krad.util.KRADConstants;
64  import org.kuali.rice.krad.util.ObjectUtils;
65  
66  import java.sql.Date;
67  import java.util.ArrayList;
68  import java.util.Collection;
69  import java.util.HashMap;
70  import java.util.Iterator;
71  import java.util.List;
72  import java.util.Map;
73  
74  /**
75   * This is a description of what this class does - jjhanso don't forget to fill this in.
76   *
77   * @author Kuali Rice Team (rice.collab@kuali.org)
78   *
79   */
80  public class RuleDelegationLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
81      private List<Row> rows = new ArrayList<Row>();
82      //private List<Column> columns = establishColumns();
83      //private Long previousRuleTemplateId;
84      private static final String PARENT_RESPONSIBILITY_ID_PROPERTY_NAME = "responsibilityId";
85      private static final String PARENT_RULE_ID_PROPERTY_NAME = "ruleResponsibility.ruleBaseValues.ruleBaseValuesId";
86      private static final String RULE_TEMPLATE_PROPERTY_NAME = "delegationRuleBaseValues.ruleTemplate.name";
87      private static final String RULE_ID_PROPERTY_NAME = "delegationRuleBaseValues.ruleBaseValuesId";
88      private static final String ACTIVE_IND_PROPERTY_NAME = "delegationRuleBaseValues.active";
89      private static final String DELEGATION_PROPERTY_NAME = "delegationType";
90      private static final String GROUP_REVIEWER_PROPERTY_NAME = "delegationRuleBaseValues.groupReviewer";
91      private static final String GROUP_REVIEWER_NAME_PROPERTY_NAME = "delegationRuleBaseValues.groupReviewerName";
92      private static final String GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME = "delegationRuleBaseValues.groupReviewerNamespace";
93      private static final String PERSON_REVIEWER_PROPERTY_NAME = "delegationRuleBaseValues.personReviewer";
94      private static final String PERSON_REVIEWER_TYPE_PROPERTY_NAME = "delegationRuleBaseValues.personReviewerType";
95      private static final String DOC_TYP_NAME_PROPERTY_NAME = "delegationRuleBaseValues.documentType.name";
96      private static final String RULE_DESC_PROPERTY_NAME = "delegationRuleBaseValues.description";
97  
98      private static final String BACK_LOCATION = "backLocation";
99      private static final String DOC_FORM_KEY = "docFormKey";
100     private static final String INVALID_WORKGROUP_ERROR = "The Group Reviewer Namespace and Name combination is not valid";
101     private static final String INVALID_PERSON_ERROR = "The Person Reviewer is not valid";
102 
103     @Override
104 	public List<Row> getRows() {
105         List<Row> superRows = super.getRows();
106         List<Row> returnRows = new ArrayList<Row>();
107         returnRows.addAll(superRows);
108         returnRows.addAll(rows);
109         return returnRows;
110     }
111 
112     @Override
113     public boolean checkForAdditionalFields(Map fieldValues) {
114         String ruleTemplateNameParam = (String) fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
115 
116         if (StringUtils.isNotBlank(ruleTemplateNameParam)) {
117             rows = new ArrayList<Row>();
118             RuleTemplate ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplateByName(ruleTemplateNameParam);
119 
120             for (RuleTemplateAttribute ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
121                 List<RemotableAttributeField> attributeFields = null;
122                 WorkflowRuleAttributeHandlerService wrahs = KewFrameworkServiceLocator
123                         .getWorkflowRuleAttributeHandlerService();
124                 String attributeName = ruleTemplateAttribute.getRuleAttribute().getName();
125                 attributeFields = wrahs.getSearchRows(attributeName);
126 
127                 List<Row> searchRows = FieldUtils.convertRemotableAttributeFields(attributeFields);
128                 rows.addAll(searchRows);
129             }
130             return true;
131         }
132         rows.clear();
133         return false;
134     }
135 
136     @Override
137     public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
138         List errors = new ArrayList();
139 
140         String parentRuleBaseValueId = fieldValues.get(PARENT_RULE_ID_PROPERTY_NAME);
141         String parentResponsibilityId = fieldValues.get(PARENT_RESPONSIBILITY_ID_PROPERTY_NAME);
142         String docTypeNameParam = fieldValues.get(DOC_TYP_NAME_PROPERTY_NAME);
143         String ruleTemplateIdParam = null;//(String) fieldValues.get(RULE_TEMPLATE_ID_PROPERTY_NAME);
144         String ruleTemplateNameParam = fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
145         String groupIdParam = fieldValues.get(GROUP_REVIEWER_PROPERTY_NAME);
146         String groupNameParam = fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
147         String groupNamespaceParam = fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
148         String networkIdParam = fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
149         String userDirectiveParam = fieldValues.get(PERSON_REVIEWER_TYPE_PROPERTY_NAME);
150         String activeParam = fieldValues.get(ACTIVE_IND_PROPERTY_NAME);
151         String delegationParam = fieldValues.get(DELEGATION_PROPERTY_NAME);
152         String ruleIdParam = fieldValues.get(RULE_ID_PROPERTY_NAME);
153         fieldValues.get(KewApiConstants.DELEGATION_WIZARD);
154         String ruleDescription = fieldValues.get(RULE_DESC_PROPERTY_NAME);
155 
156         String docTypeSearchName = null;
157         String workflowId = null;
158         String workgroupId = null;
159         String ruleTemplateId = null;
160         Boolean isActive = null;
161         String ruleId = null;
162 
163         if (ruleIdParam != null && !"".equals(ruleIdParam.trim())) {
164             try {
165                 ruleId = ruleIdParam.trim();
166             } catch (NumberFormatException e) {
167                 // TODO: KULRICE-5201 - verify that this is a reasonable initialization given that ruleId is no longer a Long
168             	ruleId = "-1";
169             }
170         }
171 
172         if (!activeParam.equals("")) {
173             if (activeParam.equals("Y")) {
174                 isActive = Boolean.TRUE;
175             } else {
176                 isActive = Boolean.FALSE;
177             }
178         }
179 
180         if (docTypeNameParam != null && !"".equals(docTypeNameParam.trim())) {
181             docTypeSearchName = docTypeNameParam.replace('*', '%');
182             docTypeSearchName = "%" + docTypeSearchName.trim() + "%";
183         }
184 
185         if (!StringUtils.isEmpty(networkIdParam)) {
186         	Person person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(networkIdParam);
187         	if (person != null) {
188         		workflowId = person.getPrincipalId();
189         	}
190         }
191 
192         if (!StringUtils.isEmpty(groupIdParam) || !StringUtils.isEmpty(groupNameParam)) {
193             Group group = null;
194             if (groupIdParam != null && !"".equals(groupIdParam)) {
195                 group = getGroupService().getGroup(groupIdParam.trim());
196             } else {
197                 if (groupNamespaceParam == null) {
198                     groupNamespaceParam = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
199                 }
200                 group = getGroupService().getGroupByNameAndNamespaceCode(groupNamespaceParam, groupNameParam.trim());
201                 if (group == null) {
202                     GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
203                 } else {
204                     workgroupId = group.getId();
205                 }
206             }
207         }
208 
209         Map<String, String> attributes = null;
210         MyColumns myColumns = new MyColumns();
211         if (StringUtils.isNotBlank(ruleTemplateNameParam) || StringUtils.isNotBlank(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
212             RuleTemplate ruleTemplate = null;
213             if (StringUtils.isNotBlank(ruleTemplateIdParam)) {
214                 ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplate(ruleTemplateIdParam);
215             } else {
216                 ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplateByName(ruleTemplateNameParam.trim());
217                 ruleTemplateId = ruleTemplate.getId();
218             }
219 
220             attributes = new HashMap<String, String>();
221             for (RuleTemplateAttribute ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
222                 /*WorkflowRuleAttribute attribute = (WorkflowRuleAttribute)GlobalResourceLoader.getObject(new ObjectDefinition(ruleTemplateAttribute.getRuleAttribute().getResourceDescriptor(), ruleTemplateAttribute.getRuleAttribute().getApplicationId()));//SpringServiceLocator.getExtensionService().getWorkflowAttribute(ruleTemplateAttribute.getRuleAttribute().getClassName());
223                 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
224                 ExtensionDefinition extensionDefinition = RuleAttribute.to(ruleAttribute);
225                 if (ruleAttribute.getType().equals(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE)) {
226                     ((GenericXMLRuleAttribute) attribute).setExtensionDefinition(extensionDefinition);
227                 }
228                 attribute.setRequired(false);*/
229                 List<RemotableAttributeField> searchRows = null;
230                 String curExtId = "0";//debugging for EN-1682
231 
232                 String attributeName = ruleTemplateAttribute.getRuleAttribute().getName();
233                 WorkflowRuleAttributeHandlerService wrahs = KewFrameworkServiceLocator.getWorkflowRuleAttributeHandlerService();
234                 ValidationResults validationResults = wrahs.validateRuleData(attributeName, fieldValues);
235                 for (Map.Entry<String, String> entry : validationResults.getErrors().entrySet()) {
236                     GlobalVariables.getMessageMap().putError(entry.getValue(), RiceKeyConstants.ERROR_CUSTOM, entry.getKey());
237                     }
238 
239                 //Validate extension data
240                 Map<String, String> curExts = ruleTemplateAttribute.getRuleExtensionMap();
241                 ValidationResults extensionValidationResults = wrahs.validateRuleData(attributeName, curExts);
242                 if (!extensionValidationResults.getErrors().isEmpty()) {
243                     for (Map.Entry<String, String> entry : extensionValidationResults.getErrors().entrySet()) {
244                         LOG.warn("Exception caught attempting to validate attribute data for extension id:" + entry.getKey() + ". Reason: " + entry.getValue());
245                     }
246                 }
247 
248                 searchRows = wrahs.getSearchRows(attributeName);
249 
250                 for (RemotableAttributeField field : searchRows) {
251                     if (fieldValues.get(field.getName()) != null) {
252                         String attributeParam = fieldValues.get(field.getName());
253                         if (StringUtils.isNotBlank(attributeParam)) {
254                             attributes.put(field.getName(), attributeParam.trim());
255                                 }
256                             }
257                     if (field.getControl() instanceof RemotableTextInput || field.getControl() instanceof RemotableSelect
258                             || field.getControl() instanceof RemotableCheckboxGroup
259                             || field.getControl() instanceof RemotableRadioButtonGroup) {
260                         myColumns.getColumns().add(new ConcreteKeyValue(field.getName(), ruleTemplateAttribute.getId()));
261                     }
262                 }
263             }
264         }
265 
266         if (!StringUtils.isEmpty(ruleDescription)) {
267             ruleDescription = ruleDescription.replace('*', '%');
268             ruleDescription = "%" + ruleDescription.trim() + "%";
269         }
270 
271         if (!GlobalVariables.getMessageMap().hasNoErrors()) {
272             throw new ValidationException("errors in search criteria");
273         }
274 
275         // TODO: replace this with new API find method ??
276         Iterator<RuleDelegationBo> rules = getRuleDelegationService().search(parentRuleBaseValueId, parentResponsibilityId, docTypeSearchName, ruleId, ruleTemplateId, ruleDescription, workgroupId, workflowId, delegationParam, isActive, attributes, userDirectiveParam).iterator();
277         List<RuleDelegationBo> displayList = new ArrayList<RuleDelegationBo>();
278 
279         while (rules.hasNext()) {
280             RuleDelegationBo ruleDelegation = rules.next();
281             RuleBaseValues record = ruleDelegation.getDelegationRule();
282 
283             if (org.apache.commons.lang.StringUtils.isEmpty(record.getDescription())) {
284                 record.setDescription(KewApiConstants.HTML_NON_BREAKING_SPACE);
285             }
286 
287             if (ruleTemplateNameParam != null && !ruleTemplateNameParam.trim().equals("") || ruleTemplateIdParam != null && !"".equals(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
288                 MyColumns myNewColumns = new MyColumns();
289                 for (Object element : myColumns.getColumns()) {
290                     KeyValue pair = (KeyValue) element;
291                     final KeyValue newPair;
292                     if (record.getRuleExtensionValue(pair.getKey(), pair.getKey().toString()) != null) {
293                     	newPair = new ConcreteKeyValue(pair.getKey(), record.getRuleExtensionValue(pair.getValue(), pair.getKey().toString()).getValue());
294                     } else {
295                     	newPair = new ConcreteKeyValue(pair.getKey(), KewApiConstants.HTML_NON_BREAKING_SPACE);
296                     }
297                     myNewColumns.getColumns().add(newPair);
298                     record.getFieldValues().put(newPair.getKey(), newPair.getValue());
299                 }
300                 record.setMyColumns(myNewColumns);
301             }
302 
303             StringBuffer returnUrl = new StringBuffer("<a href=\"");
304             returnUrl.append(fieldValues.get(BACK_LOCATION)).append("?methodToCall=refresh&docFormKey=").append(fieldValues.get(DOC_FORM_KEY)).append("&");
305 
306             returnUrl.append(RULE_ID_PROPERTY_NAME);
307             returnUrl.append("=").append(record.getId()).append("\">return value</a>");
308             record.setReturnUrl(returnUrl.toString());
309 
310             String destinationUrl = "<a href=\"Rule.do?methodToCall=report&currentRuleId=" + record.getId() + "\">report</a>";
311 
312             record.setDestinationUrl(destinationUrl);
313 
314             displayList.add(ruleDelegation);
315         }
316         return displayList;
317 
318     }
319 
320 
321 
322     private GroupService getGroupService() {
323        return KimApiServiceLocator.getGroupService();
324     }
325 
326     private RuleTemplateService getRuleTemplateService() {
327         return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
328     }
329     private RuleDelegationService getRuleDelegationService() {
330         return (RuleDelegationService) KEWServiceLocator.getService(KEWServiceLocator.RULE_DELEGATION_SERVICE);
331     }
332 
333     @Override
334     public void validateSearchParameters(Map fieldValues) {
335         super.validateSearchParameters(fieldValues);
336 
337         // make sure that if we have either groupName or Namespace, that both are filled in
338         String groupName = (String)fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
339         String groupNamespace = (String)fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
340         String principalName = (String)fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
341 
342         if (StringUtils.isEmpty(groupName) && !StringUtils.isEmpty(groupNamespace)) {
343             String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAME_PROPERTY_NAME);
344             GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
345         }
346 
347         if  (!StringUtils.isEmpty(groupName) && StringUtils.isEmpty(groupNamespace)) {
348             String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
349             GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
350         }
351 
352         if  (!StringUtils.isEmpty(groupName) && !StringUtils.isEmpty(groupNamespace)) {
353             Group group = KimApiServiceLocator.getGroupService().getGroupByNameAndNamespaceCode(groupNamespace,
354                     groupName);
355             if (group == null) {
356                 GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
357             }
358         }
359 
360         if  (!StringUtils.isEmpty(principalName)) {
361             Person person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
362             if (person == null) {
363                 GlobalVariables.getMessageMap().putError(PERSON_REVIEWER_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_PERSON_ERROR);
364             }
365         }
366         if (!GlobalVariables.getMessageMap().hasNoErrors()) {
367             throw new ValidationException("errors in search criteria");
368         }
369     }
370 
371     @Override
372     public Collection performLookup(LookupForm lookupForm,
373             Collection resultTable, boolean bounded) {
374         // TODO jjhanso - THIS METHOD NEEDS JAVADOCS
375         //return super.performLookup(lookupForm, resultTable, bounded);
376         setBackLocation((String) lookupForm.getFieldsForLookup().get(KRADConstants.BACK_LOCATION));
377         setDocFormKey((String) lookupForm.getFieldsForLookup().get(KRADConstants.DOC_FORM_KEY));
378         Collection displayList;
379 
380         // call search method to get results
381         if (bounded) {
382             displayList = getSearchResults(lookupForm.getFieldsForLookup());
383         }
384         else {
385             displayList = getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
386         }
387 
388         HashMap<String,Class> propertyTypes = new HashMap<String, Class>();
389 
390         boolean hasReturnableRow = false;
391 
392         List returnKeys = getReturnKeys();
393         List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
394         Person user = GlobalVariables.getUserSession().getPerson();
395 
396         // iterate through result list and wrap rows with return url and action urls
397         for (Iterator iter = displayList.iterator(); iter.hasNext();) {
398             BusinessObject element = (BusinessObject) iter.next();
399             if(element instanceof PersistableBusinessObject){
400                 lookupForm.setLookupObjectId(((PersistableBusinessObject)element).getObjectId());
401             }
402 
403             BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
404 
405             HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
406 
407             String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
408             //Fix for JIRA - KFSMI-2417
409             if("".equals(actionUrls)){
410                 actionUrls = ACTION_URLS_EMPTY;
411             }
412 
413             List<Column> columns = getColumns();
414             for (Object element2 : columns) {
415 
416                 Column col = (Column) element2;
417                 String curPropName = col.getPropertyName();
418                 Formatter formatter = col.getFormatter();
419 
420                 // pick off result column from result list, do formatting
421                 String propValue = KRADConstants.EMPTY_STRING;
422                 Object prop = null;
423                 boolean skipPropTypeCheck = false;
424                 //try to get value elsewhere
425                 if (element instanceof RuleDelegationBo) {
426                     prop = ((RuleDelegationBo)element).getDelegationRule().getFieldValues().get(curPropName);
427                     skipPropTypeCheck = true;
428                 }
429                 if (prop == null) {
430                     prop = ObjectUtils.getPropertyValue(element, curPropName);
431                 }
432 
433                 // set comparator and formatter based on property type
434                 Class propClass = propertyTypes.get(curPropName);
435                 if ( propClass == null && !skipPropTypeCheck) {
436                     try {
437                         propClass = ObjectUtils.getPropertyType( element, curPropName, getPersistenceStructureService() );
438                         propertyTypes.put( curPropName, propClass );
439                     } catch (Exception e) {
440                         throw new RuntimeException("Cannot access PropertyType for property " + "'" + curPropName + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
441                     }
442                 }
443 
444                 // formatters
445                 if (prop != null) {
446                     // for Booleans, always use BooleanFormatter
447                     if (prop instanceof Boolean) {
448                         formatter = new BooleanFormatter();
449                     }
450 
451                     // for Dates, always use DateFormatter
452                     if (prop instanceof Date) {
453                         formatter = new DateFormatter();
454                     }
455 
456                     // for collection, use the list formatter if a formatter hasn't been defined yet
457                     if (prop instanceof Collection && formatter == null) {
458                     formatter = new CollectionFormatter();
459                     }
460 
461                     if (formatter != null) {
462                         propValue = (String) formatter.format(prop);
463                     }
464                     else {
465                         propValue = prop.toString();
466                     }
467                 }
468 
469                 // comparator
470                 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
471                 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
472 
473                 propValue = maskValueIfNecessary(element.getClass(), curPropName, propValue, businessObjectRestrictions);
474 
475                 col.setPropertyValue(propValue);
476 
477                 if (StringUtils.isNotBlank(propValue)) {
478                     col.setColumnAnchor(getInquiryUrl(element, curPropName));
479 
480                 }
481             }
482 
483             ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
484             row.setRowId(returnUrl.getName());
485             row.setReturnUrlHtmlData(returnUrl);
486             // because of concerns of the BO being cached in session on the ResultRow,
487             // let's only attach it when needed (currently in the case of export)
488             if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
489                 row.setBusinessObject(element);
490             }
491             if(element instanceof PersistableBusinessObject){
492                 row.setObjectId((((PersistableBusinessObject)element).getObjectId()));
493             }
494 
495 
496             boolean rowReturnable = isResultReturnable(element);
497             row.setRowReturnable(rowReturnable);
498             if (rowReturnable) {
499                 hasReturnableRow = true;
500             }
501             resultTable.add(row);
502         }
503 
504         lookupForm.setHasReturnableRow(hasReturnableRow);
505 
506         return displayList;
507     }
508 
509     @Override
510     public List<Column> getColumns() {
511         List<Column> columns = super.getColumns();
512         for (Row row : rows) {
513             for (Field field : row.getFields()) {
514                 Column newColumn = new Column();
515                 newColumn.setColumnTitle(field.getFieldLabel());
516                 newColumn.setMaxLength(field.getMaxLength());
517                 newColumn.setPropertyName(field.getPropertyName());
518                 columns.add(newColumn);
519             }
520         }
521         return columns;
522     }
523 
524     @Override
525     public List<HtmlData> getCustomActionUrls(BusinessObject businessObject,
526             List pkNames) {
527         RuleDelegationBo ruleDelegation = (RuleDelegationBo)businessObject;
528         List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
529         if (StringUtils.isNotBlank(ruleDelegation.getDelegationRule().getRuleTemplateName()) && StringUtils.isNotBlank(getMaintenanceDocumentTypeName())) {
530         	if (allowsMaintenanceEditAction(businessObject)) {
531         		htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
532         	}
533             if (allowsMaintenanceNewOrCopyAction()) {
534                 htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
535             }
536         }
537             
538         return htmlDataList;
539     }
540 
541 
542 
543 }