View Javadoc

1   /*
2    * Copyright 2007-2009 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.reflect.ObjectDefinition;
20  import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
21  import org.kuali.rice.core.util.KeyLabelPair;
22  import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
23  import org.kuali.rice.kew.lookupable.MyColumns;
24  import org.kuali.rice.kew.rule.OddSearchAttribute;
25  import org.kuali.rice.kew.rule.RuleBaseValues;
26  import org.kuali.rice.kew.rule.RuleExtension;
27  import org.kuali.rice.kew.rule.WorkflowAttribute;
28  import org.kuali.rice.kew.rule.service.RuleService;
29  import org.kuali.rice.kew.rule.service.RuleTemplateService;
30  import org.kuali.rice.kew.rule.web.WebRuleUtils;
31  import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
32  import org.kuali.rice.kew.service.KEWServiceLocator;
33  import org.kuali.rice.kew.util.KEWConstants;
34  import org.kuali.rice.kew.util.Utilities;
35  import org.kuali.rice.kim.bo.Group;
36  import org.kuali.rice.kim.bo.Person;
37  import org.kuali.rice.kim.service.IdentityManagementService;
38  import org.kuali.rice.kim.service.KIMServiceLocator;
39  import org.kuali.rice.kim.util.KimConstants;
40  import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
41  import org.kuali.rice.kns.bo.BusinessObject;
42  import org.kuali.rice.kns.bo.PersistableBusinessObject;
43  import org.kuali.rice.kns.exception.ValidationException;
44  import org.kuali.rice.kns.lookup.HtmlData;
45  import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
46  import org.kuali.rice.kns.lookup.LookupableHelperService;
47  import org.kuali.rice.kns.service.KNSServiceLocator;
48  import org.kuali.rice.kns.util.GlobalVariables;
49  import org.kuali.rice.kns.util.KNSConstants;
50  import org.kuali.rice.kns.util.ObjectUtils;
51  import org.kuali.rice.kns.util.RiceKeyConstants;
52  import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
53  import org.kuali.rice.kns.web.format.BooleanFormatter;
54  import org.kuali.rice.kns.web.format.CollectionFormatter;
55  import org.kuali.rice.kns.web.format.DateFormatter;
56  import org.kuali.rice.kns.web.format.Formatter;
57  import org.kuali.rice.kns.web.struts.form.LookupForm;
58  import org.kuali.rice.kns.web.ui.Column;
59  import org.kuali.rice.kns.web.ui.Field;
60  import org.kuali.rice.kns.web.ui.ResultRow;
61  import org.kuali.rice.kns.web.ui.Row;
62  
63  import java.sql.Date;
64  import java.util.*;
65  
66  /**
67   * This is a description of what this class does - jjhanso don't forget to fill this in.
68   *
69   * @author Kuali Rice Team (rice.collab@kuali.org)
70   *
71   */
72  public class RuleBaseValuesLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
73      private List<Row> rows = new ArrayList<Row>();
74      //private List<Column> columns = establishColumns();
75      //private Long previousRuleTemplateId;
76      private LookupableHelperService ruleDelegationLookupableHelperService;
77      private List<?> delegationPkNames;
78  
79      private static final String RULE_TEMPLATE_PROPERTY_NAME = "ruleTemplate.name";
80      private static final String RULE_ID_PROPERTY_NAME = "ruleBaseValuesId";
81      private static final String RULE_TEMPLATE_ID_PROPERTY_NAME = "ruleTemplateId";
82      private static final String ACTIVE_IND_PROPERTY_NAME = "activeInd";
83      private static final String DELEGATE_RULE_PROPERTY_NAME = "delegateRule";
84      private static final String GROUP_REVIEWER_PROPERTY_NAME = "groupReviewer";
85      private static final String GROUP_REVIEWER_NAME_PROPERTY_NAME = "groupReviewerName";
86      private static final String GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME = "groupReviewerNamespace";
87      private static final String PERSON_REVIEWER_PROPERTY_NAME = "personReviewer";
88      private static final String ROLE_REVIEWER_PROPERTY_NAME = "roleReviewer";
89      private static final String PERSON_REVIEWER_TYPE_PROPERTY_NAME = "personReviewerType";
90      private static final String DOC_TYP_NAME_PROPERTY_NAME = "documentType.name";
91      private static final String RULE_DESC_PROPERTY_NAME = "description";
92  
93      private static final String DOC_TYP_LOOKUPABLE = "DocumentTypeLookupableImplService";
94      private static final String RULE_TEMPLATE_LOOKUPABLE = "RuleTemplateLookupableImplService";
95      private static final String WORKGROUP_LOOKUPABLE = "WorkGroupLookupableImplService";
96      private static final String PERSON_LOOKUPABLE = "UserLookupableImplService";
97  
98      private static final String WORKGROUP_ID_PROPERTY_NAME = "workgroupId";
99  
100     private static final String BACK_LOCATION = "backLocation";
101     private static final String DOC_FORM_KEY = "docFormKey";
102     private static final String INVALID_WORKGROUP_ERROR = "The Group Reviewer Namespace and Name combination is not valid";
103     private static final String INVALID_PERSON_ERROR = "The Person Reviewer is not valid";
104 
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 fieldValues) {
115         String ruleTemplateNameParam = (String) fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
116 
117         if (ruleTemplateNameParam != null && !ruleTemplateNameParam.equals("")) {
118             rows = new ArrayList<Row>();
119             RuleTemplate ruleTemplate = null;
120 
121             ruleTemplate = getRuleTemplateService().findByRuleTemplateName(ruleTemplateNameParam);
122 
123             int i = 0;
124             for (Iterator iter = ruleTemplate.getActiveRuleTemplateAttributes().iterator(); iter.hasNext();) {
125                 RuleTemplateAttribute ruleTemplateAttribute = (RuleTemplateAttribute) iter.next();
126                 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
127                     continue;
128                 }
129                 WorkflowAttribute attribute = ruleTemplateAttribute.getWorkflowAttribute();
130                 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
131                 if (ruleAttribute.getType().equals(KEWConstants.RULE_XML_ATTRIBUTE_TYPE)) {
132                     ((GenericXMLRuleAttribute) attribute).setRuleAttribute(ruleAttribute);
133                 }
134                 // run through the attributes fields once to populate field values we have to do this
135                 // to allow rows dependent on another row value to populate correctly in the loop below
136                 List<Row> searchRows = null;
137                 if (attribute instanceof OddSearchAttribute) {
138                     searchRows = ((OddSearchAttribute) attribute).getSearchRows();
139                 } else {
140                     searchRows = attribute.getRuleRows();
141                 }
142                 for (Iterator<Row> iterator = searchRows.iterator(); iterator.hasNext();) {
143                     Row row = iterator.next();
144                     List<Field> fields = new ArrayList<Field>();
145                     for (Iterator<Field> iterator2 = row.getFields().iterator(); iterator2.hasNext();) {
146                         Field field = (Field) iterator2.next();
147                         if (fieldValues.get(field.getPropertyName()) != null) {
148                             field.setPropertyValue(fieldValues.get(field.getPropertyName()));
149                         }
150                         fields.add(field);
151                         fieldValues.put(field.getPropertyName(), field.getPropertyValue());
152                     }
153                 }
154 
155                 if (attribute instanceof OddSearchAttribute) {
156                     ((OddSearchAttribute) attribute).validateSearchData(fieldValues);
157                 } else {
158                     attribute.validateRuleData(fieldValues);// populate attribute
159                 }
160 
161                 if (attribute instanceof OddSearchAttribute) {
162                     searchRows = ((OddSearchAttribute) attribute).getSearchRows();
163                 } else {
164                     searchRows = attribute.getRuleRows();
165                 }
166                 for (Iterator iterator = searchRows.iterator(); iterator.hasNext();) {
167                     Row row = (Row) iterator.next();
168                     List<Field> fields = new ArrayList<Field>();
169                     for (Iterator<Field> iterator2 = row.getFields().iterator(); iterator2.hasNext();) {
170                         Field field = iterator2.next();
171                         if (fieldValues.get(field.getPropertyName()) != null) {
172                             field.setPropertyValue(fieldValues.get(field.getPropertyName()));
173                         }
174                         fields.add(field);
175                         fieldValues.put(field.getPropertyName(), field.getPropertyValue());
176                     }
177                     row.setFields(fields);
178                     rows.add(row);
179 
180                 }
181 
182             }
183 
184             return true;
185         }
186         rows.clear();
187         return false;
188     }
189 
190     @Override
191     public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
192         List errors = new ArrayList();
193 
194         String docTypeNameParam = (String) fieldValues.get(DOC_TYP_NAME_PROPERTY_NAME);
195         String ruleTemplateIdParam = (String) fieldValues.get(RULE_TEMPLATE_ID_PROPERTY_NAME);
196         String ruleTemplateNameParam = (String) fieldValues.get(RULE_TEMPLATE_PROPERTY_NAME);
197         String groupIdParam = (String) fieldValues.get(GROUP_REVIEWER_PROPERTY_NAME);
198         String groupNameParam = (String) fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
199         String groupNamespaceParam = (String) fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
200         String networkIdParam = (String) fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
201         String userDirectiveParam = (String) fieldValues.get(PERSON_REVIEWER_TYPE_PROPERTY_NAME);
202         String activeParam = (String) fieldValues.get(ACTIVE_IND_PROPERTY_NAME);
203         String ruleIdParam = (String) fieldValues.get(RULE_ID_PROPERTY_NAME);
204         String ruleDescription = (String) fieldValues.get(RULE_DESC_PROPERTY_NAME);
205         String deleteSelection = (String) fieldValues.get(DELEGATE_RULE_PROPERTY_NAME);
206 
207         String docTypeSearchName = null;
208         String workflowId = null;
209         String workgroupId = null;
210         Long ruleTemplateId = null;
211         Boolean isDelegateRule = null;
212         Boolean isActive = null;
213         Long ruleId = null;
214       
215         
216         //for KULRICE-3678
217         if(deleteSelection != null && !"".equals(deleteSelection.trim()))
218         {
219         	if(deleteSelection.equalsIgnoreCase("Y"))
220         		isDelegateRule = Boolean.TRUE;
221         	else
222         		isDelegateRule = Boolean.FALSE;
223         }
224         
225         if (ruleIdParam != null && !"".equals(ruleIdParam.trim())) {
226             try {
227                 ruleId = new Long(ruleIdParam.trim());
228             } catch (NumberFormatException e) {
229                 ruleId = new Long(-1);
230             }
231         }
232 
233         if (!activeParam.equals("")) {
234             if (activeParam.equals("Y")) {
235                 isActive = Boolean.TRUE;
236             } else {
237                 isActive = Boolean.FALSE;
238             }
239         }
240 
241         if (docTypeNameParam != null && !"".equals(docTypeNameParam.trim())) {
242             docTypeSearchName = docTypeNameParam.replace('*', '%');
243             docTypeSearchName = "%" + docTypeSearchName.trim() + "%";
244         }
245 
246         if (!Utilities.isEmpty(networkIdParam)) {
247         	Person person = KIMServiceLocator.getPersonService().getPersonByPrincipalName(networkIdParam);
248         	if (person != null) {
249         		workflowId = person.getPrincipalId();
250         	}
251         }
252         
253         if (!Utilities.isEmpty(groupIdParam) || !Utilities.isEmpty(groupNameParam)) {
254             Group group = null;
255             if (groupIdParam != null && !"".equals(groupIdParam)) {
256                 group = getIdentityManagementService().getGroup(groupIdParam.trim());
257             } else {
258                 if (groupNamespaceParam == null) {
259                     groupNamespaceParam = KimConstants.KIM_GROUP_DEFAULT_NAMESPACE_CODE;
260                 }
261                 group = getIdentityManagementService().getGroupByName(groupNamespaceParam, groupNameParam.trim());
262                 if (group == null) {
263                     String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAME_PROPERTY_NAME) + ":" + getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
264                     GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
265                 } else {
266                     workgroupId = group.getGroupId();
267                 }
268             }
269         }
270 
271         Map attributes = null;
272         MyColumns myColumns = new MyColumns();
273         if (ruleTemplateNameParam != null && !ruleTemplateNameParam.trim().equals("") || ruleTemplateIdParam != null && !"".equals(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
274             RuleTemplate ruleTemplate = null;
275             if (ruleTemplateIdParam != null && !"".equals(ruleTemplateIdParam)) {
276                 ruleTemplateId = new Long(ruleTemplateIdParam);
277                 ruleTemplate = getRuleTemplateService().findByRuleTemplateId(ruleTemplateId);
278             } else {
279                 ruleTemplate = getRuleTemplateService().findByRuleTemplateName(ruleTemplateNameParam.trim());
280                 ruleTemplateId = new Long(ruleTemplate.getRuleTemplateId().longValue());
281             }
282 
283             attributes = new HashMap();
284             for (Iterator iter = ruleTemplate.getActiveRuleTemplateAttributes().iterator(); iter.hasNext();) {
285                 RuleTemplateAttribute ruleTemplateAttribute = (RuleTemplateAttribute) iter.next();
286                 if (!ruleTemplateAttribute.isWorkflowAttribute()) {
287                     continue;
288                 }
289                 WorkflowAttribute attribute = (WorkflowAttribute)GlobalResourceLoader.getObject(new ObjectDefinition(ruleTemplateAttribute.getRuleAttribute().getClassName(), ruleTemplateAttribute.getRuleAttribute().getServiceNamespace()));//SpringServiceLocator.getExtensionService().getWorkflowAttribute(ruleTemplateAttribute.getRuleAttribute().getClassName());
290                 RuleAttribute ruleAttribute = ruleTemplateAttribute.getRuleAttribute();
291                 if (ruleAttribute.getType().equals(KEWConstants.RULE_XML_ATTRIBUTE_TYPE)) {
292                     ((GenericXMLRuleAttribute) attribute).setRuleAttribute(ruleAttribute);
293                 }
294                 attribute.setRequired(false);
295                 List<Row> searchRows = null;
296 				long curExtId = 0;//debugging for EN-1682
297                 if (attribute instanceof OddSearchAttribute) {
298                     for (WorkflowServiceErrorImpl wsei : (List<WorkflowServiceErrorImpl>)((OddSearchAttribute)attribute).validateSearchData(fieldValues)) {
299                         GlobalVariables.getMessageMap().putError(wsei.getMessage(), RiceKeyConstants.ERROR_CUSTOM, wsei.getArg1());
300                     }                   
301                     try {
302 						List<RuleExtension> curExts = ruleTemplateAttribute.getRuleExtensions();
303 		                for (Iterator extIter = curExts.iterator(); extIter.hasNext();) {
304 		                	RuleExtension curExt = (RuleExtension) iter.next();
305 		                	curExtId = curExt.getRuleExtensionId();
306 		                	RuleBaseValues curRule = curExt.getRuleBaseValues();
307 							attribute.validateRuleData(WebRuleUtils.getFieldMapForRuleTemplateAttribute(curRule, ruleTemplateAttribute));
308                     }
309 					} catch (Exception e) {						
310 						LOG.warn("Exception caught attempting to validate attribute data for extension id:" + curExtId + ". Reason: " + e.getCause());
311 					}
312                     
313                     searchRows = ((OddSearchAttribute) attribute).getSearchRows();
314                 } else {
315                     for (WorkflowServiceErrorImpl wsei : (List<WorkflowServiceErrorImpl>)attribute.validateRuleData(fieldValues)) {
316                         GlobalVariables.getMessageMap().putError(wsei.getMessage(), RiceKeyConstants.ERROR_CUSTOM, wsei.getArg1());
317                     }
318                    
319 					try {
320 						List<RuleExtension> curExts = ruleTemplateAttribute.getRuleExtensions();
321 		                for (Iterator extIter = curExts.iterator(); extIter.hasNext();) {
322 		                	RuleExtension curExt = (RuleExtension) iter.next();
323 		                	curExtId = curExt.getRuleExtensionId();
324 		                	RuleBaseValues curRule = curExt.getRuleBaseValues();
325 							attribute.validateRuleData(WebRuleUtils.getFieldMapForRuleTemplateAttribute(curRule, ruleTemplateAttribute));
326 		                }
327 					} catch (Exception e) {						
328 						LOG.warn("Exception caught attempting to validate attribute data for extension id:" + curExtId + ". Reason: " + e.getCause());
329 					}
330                  
331                     searchRows = attribute.getRuleRows();
332                 }
333                 for (Row row : searchRows) {
334                     for (Field field : row.getFields()) {
335                         if (fieldValues.get(field.getPropertyName()) != null) {
336                             String attributeParam = (String) fieldValues.get(field.getPropertyName());
337                             if (!attributeParam.equals("")) {
338                                 if (ruleAttribute.getType().equals(KEWConstants.RULE_XML_ATTRIBUTE_TYPE)) {
339                                     attributes.put(field.getPropertyName(), attributeParam.trim());
340                                 } else {
341                                     attributes.put(field.getPropertyName(), attributeParam.trim());
342                                 }
343                             }
344                         }
345                         if (field.getFieldType().equals(Field.TEXT) || field.getFieldType().equals(Field.DROPDOWN) || field.getFieldType().equals(Field.DROPDOWN_REFRESH) || field.getFieldType().equals(Field.RADIO)) {
346                             if (ruleAttribute.getType().equals(KEWConstants.RULE_XML_ATTRIBUTE_TYPE)) {
347                                 myColumns.getColumns().add(new KeyLabelPair(field.getPropertyName(), ruleTemplateAttribute.getRuleTemplateAttributeId()+""));
348                             } else {
349                                 myColumns.getColumns().add(new KeyLabelPair(field.getPropertyName(), ruleTemplateAttribute.getRuleTemplateAttributeId()+""));
350                             }
351                         }
352                     }
353                 }
354             }
355         }
356 
357         if (!Utilities.isEmpty(ruleDescription)) {
358             ruleDescription = ruleDescription.replace('*', '%');
359             ruleDescription = "%" + ruleDescription.trim() + "%";
360         }
361        
362         if (!GlobalVariables.getMessageMap().isEmpty()) {
363             throw new ValidationException("errors in search criteria");
364         }
365        
366 
367         Iterator rules = getRuleService().search(docTypeSearchName, ruleId, ruleTemplateId, ruleDescription, workgroupId, workflowId, isDelegateRule, isActive, attributes, userDirectiveParam).iterator();
368         List displayList = new ArrayList();
369 
370         while (rules.hasNext()) {
371             RuleBaseValues record = (RuleBaseValues) rules.next();
372 
373             if (Utilities.isEmpty(record.getDescription())) {
374             	
375                 record.setDescription("");
376             }
377 
378             if (ruleTemplateNameParam != null && !ruleTemplateNameParam.trim().equals("") || ruleTemplateIdParam != null && !"".equals(ruleTemplateIdParam) && !"null".equals(ruleTemplateIdParam)) {
379                 MyColumns myNewColumns = new MyColumns();
380                 for (Iterator iter = myColumns.getColumns().iterator(); iter.hasNext();) {
381                     KeyLabelPair pair = (KeyLabelPair) iter.next();
382                     KeyLabelPair newPair = new KeyLabelPair();
383                     newPair.setKey(pair.getKey());
384                     if (record.getRuleExtensionValue(new Long(pair.getLabel()), pair.getKey().toString()) != null) {
385                         newPair.setLabel(record.getRuleExtensionValue(new Long(pair.getLabel()), pair.getKey().toString()).getValue());
386                     } else {
387                         newPair.setLabel("");
388                     }
389                     myNewColumns.getColumns().add(newPair);
390                     record.getFieldValues().put((String)newPair.key, newPair.label);
391                 }
392                 record.setMyColumns(myNewColumns);
393             }
394 
395             StringBuffer returnUrl = new StringBuffer("<a href=\"");
396             returnUrl.append(fieldValues.get(BACK_LOCATION)).append("?methodToCall=refresh&docFormKey=").append(fieldValues.get(DOC_FORM_KEY)).append("&");
397 
398             returnUrl.append(RULE_ID_PROPERTY_NAME);
399             returnUrl.append("=").append(record.getRuleBaseValuesId()).append("\">return value</a>");
400             record.setReturnUrl(returnUrl.toString());
401 
402             String destinationUrl = "<a href=\"Rule.do?methodToCall=report&currentRuleId=" + record.getRuleBaseValuesId() + "\">report</a>";
403 
404             record.setDestinationUrl(destinationUrl);
405 
406             displayList.add(record);
407         }
408         return displayList;
409 
410     }
411 
412 
413 
414     private IdentityManagementService getIdentityManagementService() {
415        return (IdentityManagementService) KIMServiceLocator.getService(KIMServiceLocator.KIM_IDENTITY_MANAGEMENT_SERVICE);
416     }
417 
418     private RuleTemplateService getRuleTemplateService() {
419         return (RuleTemplateService) KEWServiceLocator.getService(KEWServiceLocator.RULE_TEMPLATE_SERVICE);
420     }
421     private RuleService getRuleService() {
422         return (RuleService) KEWServiceLocator.getService(KEWServiceLocator.RULE_SERVICE);
423     }
424 
425     @Override
426     public void validateSearchParameters(Map fieldValues) {
427         super.validateSearchParameters(fieldValues);
428 
429         // make sure that if we have either groupName or Namespace, that both are filled in
430         String groupName = (String)fieldValues.get(GROUP_REVIEWER_NAME_PROPERTY_NAME);
431         String groupNamespace = (String)fieldValues.get(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
432         String principalName = (String)fieldValues.get(PERSON_REVIEWER_PROPERTY_NAME);
433 
434         if (Utilities.isEmpty(groupName) && !Utilities.isEmpty(groupNamespace)) {
435             String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAME_PROPERTY_NAME);
436             GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
437         }
438 
439         if  (!Utilities.isEmpty(groupName) && Utilities.isEmpty(groupNamespace)) {
440             String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME);
441             GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
442         }
443 
444         if  (!Utilities.isEmpty(groupName) && !Utilities.isEmpty(groupNamespace)) {
445             Group group = KIMServiceLocator.getIdentityManagementService().getGroupByName(groupNamespace, groupName);
446             if (group == null) {
447                 String attributeLabel =  getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAMESPACE_PROPERTY_NAME) + ":" + getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), GROUP_REVIEWER_NAME_PROPERTY_NAME);
448                 GlobalVariables.getMessageMap().putError(GROUP_REVIEWER_NAME_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_WORKGROUP_ERROR);
449             }
450         }
451 
452         if  (!Utilities.isEmpty(principalName)) {
453             Person person = KIMServiceLocator.getPersonService().getPersonByPrincipalName(principalName);
454             if (person == null) {
455                 String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), PERSON_REVIEWER_PROPERTY_NAME) + ":" + getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), PERSON_REVIEWER_PROPERTY_NAME);
456                 GlobalVariables.getMessageMap().putError(PERSON_REVIEWER_PROPERTY_NAME, RiceKeyConstants.ERROR_CUSTOM, INVALID_PERSON_ERROR);
457             }
458         }
459         if (!GlobalVariables.getMessageMap().isEmpty()) {
460             throw new ValidationException("errors in search criteria");
461         }
462     }
463 
464     @Override
465     public Collection performLookup(LookupForm lookupForm,
466             Collection resultTable, boolean bounded) {
467         // TODO jjhanso - THIS METHOD NEEDS JAVADOCS
468         //return super.performLookup(lookupForm, resultTable, bounded);
469         setBackLocation((String) lookupForm.getFieldsForLookup().get(KNSConstants.BACK_LOCATION));
470         setDocFormKey((String) lookupForm.getFieldsForLookup().get(KNSConstants.DOC_FORM_KEY));
471         Collection displayList;
472 
473         // call search method to get results
474         if (bounded) {
475             displayList = getSearchResults(lookupForm.getFieldsForLookup());
476         }
477         else {
478             displayList = getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
479         }
480 
481         HashMap<String,Class> propertyTypes = new HashMap<String, Class>();
482 
483         boolean hasReturnableRow = false;
484 
485         List returnKeys = getReturnKeys();
486         List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
487         Person user = GlobalVariables.getUserSession().getPerson();
488         
489         // iterate through result list and wrap rows with return url and action urls
490         for (Iterator iter = displayList.iterator(); iter.hasNext();) {
491             BusinessObject element = (BusinessObject) iter.next();
492             if(element instanceof PersistableBusinessObject){
493                 lookupForm.setLookupObjectId(((PersistableBusinessObject)element).getObjectId());
494             }
495 
496             BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
497 
498             HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
499 
500             String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
501             //Fix for JIRA - KFSMI-2417
502             if("".equals(actionUrls)){
503                 actionUrls = ACTION_URLS_EMPTY;
504             }
505 
506             // Determine whether or not this rule is a delegate rule.
507             boolean isRuleDelegation = (element instanceof RuleBaseValues && ((RuleBaseValues) element).getDelegateRule().booleanValue());
508             
509             List<Column> columns = getColumns();
510             for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
511 
512                 Column col = (Column) iterator.next();
513                 Formatter formatter = col.getFormatter();
514 
515                 // pick off result column from result list, do formatting
516                 String propValue = KNSConstants.EMPTY_STRING;
517                 Object prop = null;
518                 boolean skipPropTypeCheck = false;
519                 //try to get value elsewhere
520                 if (element instanceof RuleBaseValues) {
521                     prop = ((RuleBaseValues)element).getFieldValues().get(col.getPropertyName());
522                     skipPropTypeCheck = true;
523                 }
524                 if (prop == null) {
525                     prop = ObjectUtils.getPropertyValue(element, col.getPropertyName());
526                 }
527 
528                 // set comparator and formatter based on property type
529                 Class propClass = propertyTypes.get(col.getPropertyName());
530                 if ( propClass == null && !skipPropTypeCheck) {
531                     try {
532                         propClass = ObjectUtils.getPropertyType( element, col.getPropertyName(), getPersistenceStructureService() );
533                         propertyTypes.put( col.getPropertyName(), propClass );
534                     } catch (Exception e) {
535                         throw new RuntimeException("Cannot access PropertyType for property " + "'" + col.getPropertyName() + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
536                     }
537                 }
538 
539                 // formatters
540                 if (prop != null) {
541                     // for Booleans, always use BooleanFormatter
542                     if (prop instanceof Boolean) {
543                         formatter = new BooleanFormatter();
544                     }
545 
546                     // for Dates, always use DateFormatter
547                     if (prop instanceof Date) {
548                         formatter = new DateFormatter();
549                     }
550 
551                     // for collection, use the list formatter if a formatter hasn't been defined yet
552                     if (prop instanceof Collection && formatter == null) {
553                     formatter = new CollectionFormatter();
554                     }
555 
556                     if (formatter != null) {
557                         propValue = (String) formatter.format(prop);
558                     }
559                     else {
560                         propValue = prop.toString();
561                     }
562                 }
563 
564                 // comparator
565                 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
566                 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
567 
568                 propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
569 
570                 col.setPropertyValue(propValue);
571 
572                 if (StringUtils.isNotBlank(propValue)) {
573                 	if (RULE_ID_PROPERTY_NAME.equals(col.getPropertyName()) && isRuleDelegation) {
574                 		// If the row represents a delegate rule, make the ID column's inquiry link lead to the corresponding delegate rule instead.
575                    		List<?> delegationList = KEWServiceLocator.getRuleDelegationService().findByDelegateRuleId(
576                    				((RuleBaseValues) element).getRuleBaseValuesId());
577                 		if (ObjectUtils.isNotNull(delegationList) && !delegationList.isEmpty()) {
578                 			BusinessObject ruleDelegation = (BusinessObject) delegationList.get(0);
579                 			col.setColumnAnchor(getInquiryUrl(ruleDelegation, "ruleDelegationId"));
580                 		} else {
581                 			col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
582                 		}
583                 	}else {
584                 		col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
585                 	}
586 
587                 }
588             }
589 
590             ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
591             row.setRowId(returnUrl.getName());
592             row.setReturnUrlHtmlData(returnUrl);
593             // because of concerns of the BO being cached in session on the ResultRow,
594             // let's only attach it when needed (currently in the case of export)
595             if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
596                 row.setBusinessObject(element);
597             }
598             if(element instanceof PersistableBusinessObject){
599                 row.setObjectId((((PersistableBusinessObject)element).getObjectId()));
600             }
601 
602 
603             boolean rowReturnable = isResultReturnable(element);
604             row.setRowReturnable(rowReturnable);
605             if (rowReturnable) {
606                 hasReturnableRow = true;
607             }
608             resultTable.add(row);
609         }
610 
611         lookupForm.setHasReturnableRow(hasReturnableRow);
612 
613         return displayList;
614     }
615 
616     @Override
617     public List<Column> getColumns() {
618         List<Column> columns = super.getColumns();
619         for (Row row : rows) {
620             for (Field field : row.getFields()) {
621                 Column newColumn = new Column();
622                 newColumn.setColumnTitle(field.getFieldLabel());
623                 newColumn.setMaxLength(field.getMaxLength());
624                 newColumn.setPropertyName(field.getPropertyName());
625                 columns.add(newColumn);
626             }
627         }
628         return columns;
629     }
630 
631     @Override
632     public List<HtmlData> getCustomActionUrls(BusinessObject businessObject,
633             List pkNames) {
634         RuleBaseValues ruleBaseValues = (RuleBaseValues)businessObject;
635         List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
636         if (StringUtils.isNotBlank(ruleBaseValues.getRuleTemplateName()) && StringUtils.isNotBlank(getMaintenanceDocumentTypeName())) {
637         	if (ruleBaseValues.getDelegateRule().booleanValue()) {
638         		// If the rule is a delegate rule, have the edit/copy links open the rule delegation maintenance document screen instead.
639         		List<?> delegationList = KEWServiceLocator.getRuleDelegationService().findByDelegateRuleId(ruleBaseValues.getRuleBaseValuesId());
640         		if (ObjectUtils.isNotNull(delegationList) && !delegationList.isEmpty()) {
641         			BusinessObject ruleDelegation = (BusinessObject) delegationList.get(0);
642     				// Retrieve the rule delegation lookupable helper service and the primary key names, if they have not been obtained yet.
643         	        if (ruleDelegationLookupableHelperService == null) {
644         				ruleDelegationLookupableHelperService = KNSServiceLocator.getLookupable(
645         						KNSServiceLocator.getBusinessObjectDictionaryService().getLookupableID(
646         								ruleDelegation.getClass())).getLookupableHelperService();
647         				if (ruleDelegationLookupableHelperService.getBusinessObjectClass() == null) {
648         					ruleDelegationLookupableHelperService.setBusinessObjectClass(ruleDelegation.getClass());
649         				}
650         				delegationPkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(ruleDelegation.getClass());
651         			}
652         	        // Allow the rule delegation's lookupable helper service to handle the custom action URL generation instead.
653         			htmlDataList = ruleDelegationLookupableHelperService.getCustomActionUrls(ruleDelegation, delegationPkNames);
654         		}
655         	} else {
656         		// Otherwise, have the links open the regular routing rule maintenance document screen.
657         		if (allowsMaintenanceEditAction(businessObject)) {
658         			htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
659         		}
660         		if (allowsMaintenanceNewOrCopyAction()) {
661                 	htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
662             	}
663         	}
664         }
665         
666         return htmlDataList;
667     }
668 
669 
670 
671 }