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