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