001    /**
002     * Copyright 2005-2014 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kew.rule.bo;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.core.api.uif.RemotableAttributeError;
020    import org.kuali.rice.core.api.util.ConcreteKeyValue;
021    import org.kuali.rice.core.api.util.KeyValue;
022    import org.kuali.rice.core.api.util.RiceKeyConstants;
023    import org.kuali.rice.core.web.format.BooleanFormatter;
024    import org.kuali.rice.core.web.format.CollectionFormatter;
025    import org.kuali.rice.core.web.format.DateFormatter;
026    import org.kuali.rice.core.web.format.Formatter;
027    import org.kuali.rice.kew.api.KewApiConstants;
028    import org.kuali.rice.kew.api.KewApiServiceLocator;
029    import org.kuali.rice.kew.api.rule.RuleTemplate;
030    import org.kuali.rice.kew.api.rule.RuleTemplateAttribute;
031    import org.kuali.rice.kew.lookupable.MyColumns;
032    import org.kuali.rice.kew.rule.RuleBaseValues;
033    import org.kuali.rice.kew.rule.RuleDelegationBo;
034    import org.kuali.rice.kew.rule.RuleExtensionBo;
035    import org.kuali.rice.kew.rule.WorkflowRuleAttributeRows;
036    import org.kuali.rice.kew.rule.service.RuleDelegationService;
037    import org.kuali.rice.kew.rule.service.RuleTemplateService;
038    import org.kuali.rice.kew.service.KEWServiceLocator;
039    import org.kuali.rice.kim.api.KimConstants;
040    import org.kuali.rice.kim.api.group.Group;
041    import org.kuali.rice.kim.api.group.GroupService;
042    import org.kuali.rice.kim.api.identity.Person;
043    import org.kuali.rice.kim.api.identity.principal.Principal;
044    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
045    import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions;
046    import org.kuali.rice.kns.lookup.HtmlData;
047    import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
048    import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
049    import org.kuali.rice.kns.web.struts.form.LookupForm;
050    import org.kuali.rice.kns.web.ui.Column;
051    import org.kuali.rice.kns.web.ui.Field;
052    import org.kuali.rice.kns.web.ui.ResultRow;
053    import org.kuali.rice.kns.web.ui.Row;
054    import org.kuali.rice.krad.bo.BusinessObject;
055    import org.kuali.rice.krad.bo.PersistableBusinessObject;
056    import org.kuali.rice.krad.exception.ValidationException;
057    import org.kuali.rice.krad.util.GlobalVariables;
058    import org.kuali.rice.krad.util.KRADConstants;
059    import org.kuali.rice.krad.util.ObjectUtils;
060    
061    import java.sql.Date;
062    import java.util.ArrayList;
063    import java.util.Collection;
064    import java.util.HashMap;
065    import java.util.Iterator;
066    import java.util.List;
067    import java.util.Map;
068    
069    /**
070     * This is a description of what this class does - jjhanso don't forget to fill this in.
071     *
072     * @author Kuali Rice Team (rice.collab@kuali.org)
073     *
074     */
075    public class RuleDelegationLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
076        private List<Row> rows = new ArrayList<Row>();
077        //private List<Column> columns = establishColumns();
078        //private Long previousRuleTemplateId;
079        private static final String PARENT_RESPONSIBILITY_ID_PROPERTY_NAME = "responsibilityId";
080        private static final String PARENT_RULE_ID_PROPERTY_NAME = "ruleResponsibility.ruleBaseValuesId";
081        private static final String RULE_TEMPLATE_PROPERTY_NAME = "delegationRule.ruleTemplate.name";
082        private static final String RULE_ID_PROPERTY_NAME = "delegationRule.id";
083        private static final String ACTIVE_IND_PROPERTY_NAME = "delegationRule.active";
084        private static final String DELEGATION_PROPERTY_NAME = "delegationType";
085        private static final String GROUP_REVIEWER_PROPERTY_NAME = "groupReviewer";
086        private static final String GROUP_REVIEWER_NAME_PROPERTY_NAME = "groupReviewerName";
087        private static final String GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME = "groupReviewerNamespace";
088        private static final String PERSON_REVIEWER_PROPERTY_NAME = "personReviewer";
089        private static final String PERSON_REVIEWER_TYPE_PROPERTY_NAME = "personReviewerType";
090        private static final String DOC_TYP_NAME_PROPERTY_NAME = "delegationRule.documentType.name";
091        private static final String RULE_DESC_PROPERTY_NAME = "delegationRule.description";
092    
093        private static final String BACK_LOCATION = "backLocation";
094        private static final String DOC_FORM_KEY = "docFormKey";
095        private static final String INVALID_WORKGROUP_ERROR = "The Group Reviewer Namespace and Name combination is not valid";
096        private static final String INVALID_PERSON_ERROR = "The Person Reviewer is not valid";
097    
098        @Override
099            public List<Row> getRows() {
100            List<Row> superRows = super.getRows();
101            List<Row> returnRows = new ArrayList<Row>();
102            returnRows.addAll(superRows);
103            returnRows.addAll(rows);
104            return returnRows;
105        }
106    
107        @Override
108        public boolean checkForAdditionalFields(Map<String, String> fieldValues) {
109            String ruleTemplateNameParam = fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
110    
111            if (StringUtils.isNotBlank(ruleTemplateNameParam)) {
112                rows = new ArrayList<Row>();
113                RuleTemplate ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplateByName(ruleTemplateNameParam);
114    
115                for (RuleTemplateAttribute ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
116                    if (!RuleAttribute.isWorkflowAttribute(ruleTemplateAttribute.getRuleAttribute().getType())) {
117                        continue;
118                    }
119                    // run through the attributes fields once to populate field values we have to do this
120                    // to allow rows dependent on another row value to populate correctly in the loop below
121                    WorkflowRuleAttributeRows workflowRuleAttributeRows =
122                            KEWServiceLocator.getWorkflowRuleAttributeMediator().getSearchRows(fieldValues, ruleTemplateAttribute);
123                    for (Row row : workflowRuleAttributeRows.getRows()) {
124                        List<Field> fields = new ArrayList<Field>();
125                        for (Iterator<Field> iterator2 = row.getFields().iterator(); iterator2.hasNext(); ) {
126                            Field field = (Field) iterator2.next();
127                            if (fieldValues.get(field.getPropertyName()) != null) {
128                                field.setPropertyValue(fieldValues.get(field.getPropertyName()));
129                            }
130                            fields.add(field);
131                            fieldValues.put(field.getPropertyName(), field.getPropertyValue());
132                        }
133                    }
134                    // now run through a second time with our shiny new field values
135                    // ...by the way, just trying to preserve behavior from Rice 1.0.x here...generally speaking, this stuff is crazy!!!
136                    workflowRuleAttributeRows =
137                            KEWServiceLocator.getWorkflowRuleAttributeMediator().getSearchRows(fieldValues, ruleTemplateAttribute);
138                    for (Row row : workflowRuleAttributeRows.getRows()) {
139                        List<Field> fields = new ArrayList<Field>();
140                        for (Iterator<Field> iterator2 = row.getFields().iterator(); iterator2.hasNext(); ) {
141                            Field field = iterator2.next();
142                            if (fieldValues.get(field.getPropertyName()) != null) {
143                                field.setPropertyValue(fieldValues.get(field.getPropertyName()));
144                            }
145                            fields.add(field);
146                            fieldValues.put(field.getPropertyName(), field.getPropertyValue());
147                        }
148                        row.setFields(fields);
149                        rows.add(row);
150    
151                    }
152                }
153                return true;
154            }
155            rows.clear();
156            return false;
157        }
158    
159        @Override
160        public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
161            String parentRuleBaseValueId = fieldValues.get(PARENT_RULE_ID_PROPERTY_NAME);
162            String parentResponsibilityId = fieldValues.get(PARENT_RESPONSIBILITY_ID_PROPERTY_NAME);
163            String docTypeNameParam = fieldValues.get(DOC_TYP_NAME_PROPERTY_NAME);
164            String ruleTemplateIdParam = null;
165            String ruleTemplateNameParam = fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
166            String groupIdParam = fieldValues.get(GROUP_REVIEWER_PROPERTY_NAME);
167            String groupNameParam = fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
168            String groupNamespaceParam = fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
169            String networkIdParam = fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
170            String userDirectiveParam = fieldValues.get(PERSON_REVIEWER_TYPE_PROPERTY_NAME);
171            String activeParam = fieldValues.get(ACTIVE_IND_PROPERTY_NAME);
172            String delegationParam = fieldValues.get(DELEGATION_PROPERTY_NAME);
173            String ruleIdParam = fieldValues.get(RULE_ID_PROPERTY_NAME);
174            String ruleDescription = fieldValues.get(RULE_DESC_PROPERTY_NAME);
175    
176            String docTypeSearchName = null;
177            String workflowId = null;
178            String workgroupId = null;
179            String ruleTemplateId = null;
180            Boolean isActive = null;
181            String ruleId = null;
182    
183            if (ruleIdParam != null && !"".equals(ruleIdParam.trim())) {
184                ruleId = ruleIdParam.trim();
185            }
186    
187            if (!activeParam.equals("")) {
188                if (activeParam.equals("Y")) {
189                    isActive = Boolean.TRUE;
190                } else {
191                    isActive = Boolean.FALSE;
192                }
193            }
194    
195            if (docTypeNameParam != null && !"".equals(docTypeNameParam.trim())) {
196                docTypeSearchName = docTypeNameParam.replace('*', '%');
197                docTypeSearchName = "%" + docTypeSearchName.trim() + "%";
198            }
199    
200            if (StringUtils.isNotBlank(networkIdParam)) {
201                Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(networkIdParam);
202                    if (principal != null) {
203                            workflowId = principal.getPrincipalId();
204                    }
205            }
206    
207            if (StringUtils.isNotBlank(groupIdParam) || StringUtils.isNotBlank(groupNameParam)) {
208                Group group = null;
209                if (groupIdParam != null && !"".equals(groupIdParam)) {
210                    group = getGroupService().getGroup(groupIdParam.trim());
211                } else {
212                    if (groupNamespaceParam == null) {
213                        groupNamespaceParam = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
214                    }
215                    group = getGroupService().getGroupByNamespaceCodeAndName(groupNamespaceParam, groupNameParam.trim());
216                    if (group == null) {
217                        GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
218                    } else {
219                        workgroupId = group.getId();
220                    }
221                }
222            }
223    
224            Map<String, String> attributes = null;
225            MyColumns myColumns = new MyColumns();
226            if (StringUtils.isNotBlank(ruleTemplateNameParam) || StringUtils.isNotBlank(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
227                RuleTemplate ruleTemplate = null;
228                if (StringUtils.isNotBlank(ruleTemplateIdParam)) {
229                    ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplate(ruleTemplateIdParam);
230                } else {
231                    ruleTemplate = KewApiServiceLocator.getRuleService().getRuleTemplateByName(ruleTemplateNameParam.trim());
232                    ruleTemplateId = ruleTemplate.getId();
233                }
234    
235                if (ruleTemplate == null) {
236                    rows.clear();
237                    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.");
238                    return new ArrayList<RuleDelegationBo>();
239                }
240    
241                attributes = new HashMap<String, String>();
242    
243                for (RuleTemplateAttribute ruleTemplateAttribute : ruleTemplate.getActiveRuleTemplateAttributes()) {
244                    if (!RuleAttribute.isWorkflowAttribute(ruleTemplateAttribute.getRuleAttribute().getType())) {
245                        continue;
246                    }
247                    WorkflowRuleAttributeRows workflowRuleAttributeRows =
248                            KEWServiceLocator.getWorkflowRuleAttributeMediator().getSearchRows(fieldValues, ruleTemplateAttribute, false);
249    
250                    for (RemotableAttributeError error : workflowRuleAttributeRows.getValidationErrors()) {
251                        GlobalVariables.getMessageMap().putError(error.getAttributeName(), RiceKeyConstants.ERROR_CUSTOM, error.getMessage());
252                    }
253    
254                    for (Row row : workflowRuleAttributeRows.getRows()) {
255                        for (Field field : row.getFields()) {
256                            if (fieldValues.get(field.getPropertyName()) != null) {
257                                String attributeParam = fieldValues.get(field.getPropertyName());
258                                if (!attributeParam.equals("")) {
259                                    attributes.put(field.getPropertyName(), attributeParam.trim());
260                                }
261                            }
262                            if (field.getFieldType().equals(Field.TEXT) || field.getFieldType().equals(Field.DROPDOWN) || field.getFieldType().equals(Field.DROPDOWN_REFRESH) || field.getFieldType().equals(Field.RADIO)) {
263                                myColumns.getColumns().add(new ConcreteKeyValue(field.getPropertyName(), ruleTemplateAttribute.getId()));
264                            }
265                        }
266                    }
267                }
268            }
269    
270            if (StringUtils.isNotBlank(ruleDescription)) {
271                ruleDescription = ruleDescription.replace('*', '%');
272                ruleDescription = "%" + ruleDescription.trim() + "%";
273            }
274    
275            if (GlobalVariables.getMessageMap().hasErrors()) {
276                throw new ValidationException("errors in search criteria");
277            }
278    
279            // TODO: replace this with new API find method ??
280            Iterator<RuleDelegationBo> rules = getRuleDelegationService().search(parentRuleBaseValueId, parentResponsibilityId, docTypeSearchName, ruleId, ruleTemplateId, ruleDescription, workgroupId, workflowId, delegationParam, isActive, attributes, userDirectiveParam).iterator();
281            List<RuleDelegationBo> displayList = new ArrayList<RuleDelegationBo>();
282    
283            while (rules.hasNext()) {
284                RuleDelegationBo ruleDelegation = rules.next();
285                RuleBaseValues record = ruleDelegation.getDelegationRule();
286    
287                if (StringUtils.isBlank(record.getDescription())) {
288                    record.setDescription(KewApiConstants.HTML_NON_BREAKING_SPACE);
289                }
290    
291                if (ruleTemplateNameParam != null && !ruleTemplateNameParam.trim().equals("") || ruleTemplateIdParam != null && !"".equals(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
292                    MyColumns myNewColumns = new MyColumns();
293                    for (Object element : myColumns.getColumns()) {
294                        KeyValue pair = (KeyValue) element;
295                        final KeyValue newPair;
296                        List<RuleExtensionBo> ruleExts = record.getRuleExtensions();
297                        for (RuleExtensionBo ruleExt : ruleExts) {
298                            if(ruleExt.getExtensionValuesMap().containsKey(pair.getKey().toString())){
299                                ruleTemplateIdParam = ruleExt.getRuleTemplateAttributeId();
300                            }
301                        }
302                        if (record.getRuleExtensionValue(ruleTemplateIdParam, pair.getKey().toString()) != null) {
303                            newPair = new ConcreteKeyValue(pair.getKey(), record.getRuleExtensionValue(ruleTemplateIdParam, pair.getKey().toString()).getValue());
304                        } else {
305                            newPair = new ConcreteKeyValue(pair.getKey(), KewApiConstants.HTML_NON_BREAKING_SPACE);
306                        }
307                        myNewColumns.getColumns().add(newPair);
308                        record.getFieldValues().put(newPair.getKey(), newPair.getValue());
309                    }
310                    record.setMyColumns(myNewColumns);
311                }
312    
313                StringBuilder returnUrl = new StringBuilder("<a href=\"");
314                returnUrl.append(fieldValues.get(BACK_LOCATION)).append("?methodToCall=refresh&docFormKey=").append(fieldValues.get(DOC_FORM_KEY)).append("&");
315    
316                returnUrl.append(RULE_ID_PROPERTY_NAME);
317                returnUrl.append("=").append(record.getId()).append("\">return value</a>");
318                record.setReturnUrl(returnUrl.toString());
319    
320                String destinationUrl = "<a href=\"Rule.do?methodToCall=report&currentRuleId=" + record.getId() + "\">report</a>";
321    
322                record.setDestinationUrl(destinationUrl);
323    
324                displayList.add(ruleDelegation);
325            }
326            return displayList;
327    
328        }
329    
330    
331    
332        private GroupService getGroupService() {
333           return KimApiServiceLocator.getGroupService();
334        }
335    
336        private RuleTemplateService getRuleTemplateService() {
337            return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
338        }
339        private RuleDelegationService getRuleDelegationService() {
340            return (RuleDelegationService) KEWServiceLocator.getService(KEWServiceLocator.RULE_DELEGATION_SERVICE);
341        }
342    
343        @Override
344        public void validateSearchParameters(Map<String, String> fieldValues) {
345            super.validateSearchParameters(fieldValues);
346    
347            // make sure that if we have either groupName or Namespace, that both are filled in
348            String groupName = (String)fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
349            String groupNamespace = (String)fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
350            String principalName = (String)fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
351    
352            if (StringUtils.isEmpty(groupName) && !StringUtils.isEmpty(groupNamespace)) {
353                String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAME_PROPERTY_NAME);
354                GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
355            }
356    
357            if  (!StringUtils.isEmpty(groupName) && StringUtils.isEmpty(groupNamespace)) {
358                String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
359                GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
360            }
361    
362            if  (!StringUtils.isEmpty(groupName) && !StringUtils.isEmpty(groupNamespace)) {
363                Group group = KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(groupNamespace,
364                        groupName);
365                if (group == null) {
366                    GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
367                }
368            }
369    
370            if  (!StringUtils.isEmpty(principalName)) {
371                Person person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
372                if (person == null) {
373                    GlobalVariables.getMessageMap().putError(PERSON_REVIEWER_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_PERSON_ERROR);
374                }
375            }
376            if (!GlobalVariables.getMessageMap().hasNoErrors()) {
377                throw new ValidationException("errors in search criteria");
378            }
379        }
380    
381        @Override
382        public Collection performLookup(LookupForm lookupForm,
383                Collection resultTable, boolean bounded) {
384            // TODO jjhanso - THIS METHOD NEEDS JAVADOCS
385            //return super.performLookup(lookupForm, resultTable, bounded);
386            setBackLocation((String) lookupForm.getFieldsForLookup().get(KRADConstants.BACK_LOCATION));
387            setDocFormKey((String) lookupForm.getFieldsForLookup().get(KRADConstants.DOC_FORM_KEY));
388            Collection displayList;
389    
390            // call search method to get results
391            if (bounded) {
392                displayList = getSearchResults(lookupForm.getFieldsForLookup());
393            }
394            else {
395                displayList = getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
396            }
397    
398            HashMap<String,Class> propertyTypes = new HashMap<String, Class>();
399    
400            boolean hasReturnableRow = false;
401    
402            List returnKeys = getReturnKeys();
403            List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
404            Person user = GlobalVariables.getUserSession().getPerson();
405    
406            // iterate through result list and wrap rows with return url and action urls
407            for (Iterator iter = displayList.iterator(); iter.hasNext();) {
408                BusinessObject element = (BusinessObject) iter.next();
409                if(element instanceof PersistableBusinessObject){
410                    lookupForm.setLookupObjectId(((PersistableBusinessObject)element).getObjectId());
411                }
412    
413                BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
414    
415                HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
416    
417                String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
418                //Fix for JIRA - KFSMI-2417
419                if("".equals(actionUrls)){
420                    actionUrls = ACTION_URLS_EMPTY;
421                }
422    
423                List<Column> columns = getColumns();
424                for (Object element2 : columns) {
425    
426                    Column col = (Column) element2;
427                    String curPropName = col.getPropertyName();
428                    Formatter formatter = col.getFormatter();
429    
430                    // pick off result column from result list, do formatting
431                    String propValue = KRADConstants.EMPTY_STRING;
432                    Object prop = null;
433                    boolean skipPropTypeCheck = false;
434                    //try to get value elsewhere
435                    if (element instanceof RuleDelegationBo) {
436                        prop = ((RuleDelegationBo)element).getDelegationRule().getFieldValues().get(curPropName);
437                        skipPropTypeCheck = true;
438                    }
439                    if (prop == null) {
440                        prop = ObjectUtils.getPropertyValue(element, curPropName);
441                    }
442    
443                    // set comparator and formatter based on property type
444                    Class propClass = propertyTypes.get(curPropName);
445                    if ( propClass == null && !skipPropTypeCheck) {
446                        try {
447                            propClass = ObjectUtils.getPropertyType( element, curPropName, getPersistenceStructureService() );
448                            propertyTypes.put( curPropName, propClass );
449                        } catch (Exception e) {
450                            throw new RuntimeException("Cannot access PropertyType for property " + "'" + curPropName + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
451                        }
452                    }
453    
454                    // formatters
455                    if (prop != null) {
456                        // for Booleans, always use BooleanFormatter
457                        if (prop instanceof Boolean) {
458                            formatter = new BooleanFormatter();
459                        }
460    
461                        // for Dates, always use DateFormatter
462                        if (prop instanceof Date) {
463                            formatter = new DateFormatter();
464                        }
465    
466                        // for collection, use the list formatter if a formatter hasn't been defined yet
467                        if (prop instanceof Collection && formatter == null) {
468                        formatter = new CollectionFormatter();
469                        }
470    
471                        if (formatter != null) {
472                            propValue = (String) formatter.format(prop);
473                        }
474                        else {
475                            propValue = prop.toString();
476                        }
477                    }
478    
479                    // comparator
480                    col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
481                    col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
482    
483                    propValue = maskValueIfNecessary(element.getClass(), curPropName, propValue, businessObjectRestrictions);
484    
485                    col.setPropertyValue(propValue);
486    
487                    if (StringUtils.isNotBlank(propValue)) {
488                        col.setColumnAnchor(getInquiryUrl(element, curPropName));
489    
490                    }
491                }
492    
493                ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
494                row.setRowId(returnUrl.getName());
495                row.setReturnUrlHtmlData(returnUrl);
496                // because of concerns of the BO being cached in session on the ResultRow,
497                // let's only attach it when needed (currently in the case of export)
498                if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
499                    row.setBusinessObject(element);
500                }
501                if(element instanceof PersistableBusinessObject){
502                    row.setObjectId((((PersistableBusinessObject)element).getObjectId()));
503                }
504    
505    
506                boolean rowReturnable = isResultReturnable(element);
507                row.setRowReturnable(rowReturnable);
508                if (rowReturnable) {
509                    hasReturnableRow = true;
510                }
511                resultTable.add(row);
512            }
513    
514            lookupForm.setHasReturnableRow(hasReturnableRow);
515    
516            return displayList;
517        }
518    
519        @Override
520        public List<Column> getColumns() {
521            List<Column> columns = super.getColumns();
522            for (Row row : rows) {
523                for (Field field : row.getFields()) {
524                    Column newColumn = new Column();
525                    newColumn.setColumnTitle(field.getFieldLabel());
526                    newColumn.setMaxLength(field.getMaxLength());
527                    newColumn.setPropertyName(field.getPropertyName());
528                    columns.add(newColumn);
529                }
530            }
531            return columns;
532        }
533    
534        @Override
535        public List<HtmlData> getCustomActionUrls(BusinessObject businessObject,
536                List pkNames) {
537            RuleDelegationBo ruleDelegation = (RuleDelegationBo)businessObject;
538            List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
539            if (StringUtils.isNotBlank(ruleDelegation.getDelegationRule().getRuleTemplateName()) && StringUtils.isNotBlank(getMaintenanceDocumentTypeName())) {
540                    if (allowsMaintenanceEditAction(businessObject)) {
541                            htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
542                    }
543                if (allowsMaintenanceNewOrCopyAction()) {
544                    htmlDataList.add(getUrlData(businessObject, KRADConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
545                }
546            }
547                
548            return htmlDataList;
549        }
550    
551    
552    
553    }