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